keystone-2014.1/0000775000175400017540000000000012323716511014601 5ustar jenkinsjenkins00000000000000keystone-2014.1/HACKING.rst0000664000175400017540000000137012323716272016404 0ustar jenkinsjenkins00000000000000Keystone Style Commandments =========================== - Step 1: Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ - Step 2: Read on Keystone Specific Commandments ------------------------------ - Avoid using "double quotes" where you can reasonably use 'single quotes' TODO vs FIXME ------------- - TODO(name): implies that something should be done (cleanup, refactoring, etc), but is expected to be functional. - FIXME(name): implies that the method/function/etc shouldn't be used until that code is resolved and bug fixed. Logging ------- Use the common logging module, and ensure you ``getLogger``:: from keystone.openstack.common import log LOG = log.getLogger(__name__) LOG.debug('Foobar') keystone-2014.1/CONTRIBUTING.rst0000664000175400017540000000103612323716267017252 0ustar jenkinsjenkins00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in the "If you're a developer, start here" section of this page: http://wiki.openstack.org/HowToContribute Once those steps have been completed, changes to OpenStack should be submitted for review via the Gerrit tool, following the workflow documented at: http://wiki.openstack.org/GerritWorkflow Pull requests submitted through GitHub will be ignored. Bugs should be filed on Launchpad, not GitHub: https://bugs.launchpad.net/keystone keystone-2014.1/.mailmap0000664000175400017540000000245212323716267016235 0ustar jenkinsjenkins00000000000000# Format is: # # Joe Gordon Sirish Bitra sirish.bitra Sirish Bitra sirishbitra Sirish Bitra root Zhongyue Luo Chmouel Boudjnah Zhenguo Niu keystone-2014.1/test-requirements.txt0000664000175400017540000000152412323716272021050 0ustar jenkinsjenkins00000000000000hacking>=0.8.0,<0.9 # Optional backend: SQL pysqlite # Optional backend: Memcache python-memcached>=1.48 # Optional dogpile backend: MongoDB pymongo>=2.4 # Optional backend: LDAP # authenticate against an existing LDAP server python-ldap==2.3.13 # Testing # computes code coverage percentages coverage>=3.6 # fixture stubbing fixtures>=0.3.14 # mock object framework mock>=1.0 mox>=0.5.3 # required to build documentation sphinx>=1.1.2,<1.2 # test wsgi apps without starting an http server WebTest>=2.0 discover python-subunit>=0.0.18 testrepository>=0.0.18 testtools>=0.9.34 testscenarios>=0.4 # for python-keystoneclient # keystoneclient <0.2.1 httplib2>=0.7.5 # replaces httplib2 in keystoneclient >=0.2.1 requests>=1.1 keyring>=1.6.1,<2.0,>=2.1 # For documentation oslosphinx # Used only by oslo kombu>=2.4.8 lockfile>=0.8 stevedore>=0.14 keystone-2014.1/.coveragerc0000664000175400017540000000016212323716267016731 0ustar jenkinsjenkins00000000000000[run] branch = True source = keystone omit = keystone/tests/*,keystone/openstack/* [report] ignore-errors = True keystone-2014.1/ChangeLog0000664000175400017540000041741212323716511016364 0ustar jenkinsjenkins00000000000000CHANGES ======= 2014.1 ------ * Updated from global requirements * Fix invalid LDAP filter for user ID with comma * Remove legacy_endpoint_id and enabled from service catalog * Keystone doesn't use pam * For ldap, API wrongly reports user is in group * Sync from oslo db.sqlalchemy.migration * Sanitizes authentication methods received in requests * Fix create_region_with_id raise 500 Error bug * Fix Jenkins translation jobs 2014.1.rc1 ---------- * Enable lazy translations in httpd/keystone.py * Avoid using .values() on the indexed columns * Imported Translations from Transifex * revert deprecation of v2 API * exclude disabled services from the catalog * refactor AuthCatalog tests * Rename keystone.tests.fixtures * Change the default version discovery URLs * Remove extra cache layer debugging * Updated from global requirements * Fix doc build errors with SQLAlchemy 0.9 * Sync oslo-incubator db.sqlalchemy b9e2499 * Create TMPDIR for tests recursively * Always include 'enabled' field in service response * test tcp_keepidle only if it's available on the current platform * Add dedicated URL for issuing unscoped federation tokens * Filter SAML2 assertion parameters with certain prefix * Add support for parallel testr workers in Keystone * is_revoked check all viable subtrees * update sample conf * explicitly import gettext function * expires_at should be in a tuple not turned into one * Comparisons should account for instantaneous test execution * Uses generator expressions instead of filter * Ability to turn off ldap referral chasing * Add user_id when calling populate_roles_for_groups * Store groups ids objects list in the OS-FEDERATION object * Make domain_id immutable by default * Do not expose internal data on UnexpectedError * Use oslo db.sqlalchemy.session.EngineFacade.from_config * Uses explicit imports for _ * Rename scope_to_bad_project() to test_scope_to_bad_project() * Make LIVE Tests configurable with ENV * Filter out nonstring environment variables before rules mapping * Provide option to make domain_id immutable * Replace httplib.HTTPSConnection in ec2_token * Move test .conf files to keystone/tests/config_files * Removal of test .conf files * Don't automatically enable revocation events * Ensure v3policysample correctly limits domain_admin access * Sync db, db.sqlalchemy from oslo-incubator 0a3436f * Do not use keystone.conf.sample in tests * Filter LDAP dumb member when listing role assignments * Updated from global requirements * Remove unnecessary oauth1.Manager constructions * Enforce groups presence for federated authn * Update sample config * Very minor cleanup to default_fixtures * Cleanup keystoneclient tests * Cleanup fixture data added to test instances * Cleans up test data from limit tests * Cleanup of instance attrs in core tests * Cleanup backends after each test * Fixup region description uniqueness * Add missing documentation for enabling oauth1 auth plugin * Add missing documentation for enabling federation auth plugin * Use class attribute to represent 'user' and 'group' * Configurable temporary directory for tests * Call an existing method in sync cache for revoke events * Remove unnecessary calls to self.config() * remove hardcoded SQL queries in tests * Fix db_version failed with wrong arguments * Use config fixture * Fix docstrings in federation related modules * Sync db, db.sqlalchemy, gettextutils from oslo-incubator 6ba44fd * V3 xml responses should use v3 namespace * trust creation allowed with empty roles list * Fix include only enabled endpoints in catalog * Add unit tests for disabled endpoints in catalog 2014.1.b3 --------- * Update ADMIN_TOKEN description in docs * Mark revoke as experimental * Import order is fixed * Remove unused function from tests * Add OS-OAUTH1 to consumers links section * Don't need session.flush in context managed by session * Imported Translations from Transifex * allow create credential with the system admin token * Stop gating on up-to-date sample config file * Always include 'enabled' field in endpoint response * Add the last of the outstanding helpstrings to config * Token Revocation Extension * Remove vim headers * Removes use of timeutils.set_time_override * drop key distribution from icehouse * Limited use trusts * Update curl api example to specify tenant * Update Oslo wiki link in README * Properly configure OS-EP-FILTER test backend * Add tests for endpoint enabled * Remove the un-used and non-maintained PAM identity backend * Remove paste_deploy from test_overrides.conf * SQLAlchemy Change to support more strict dialect checking * Remove "test-only" pam config options * Imported Translations from Transifex * Fix get project users when no user exists * deprecate XML support in favor of JSON * Lazy gettextutils behavior * Update Oslo wiki link in README * Removes a redundant test * Remove unused variable * Implement V3 Specific Version of EC2 Contrib * revocation_list only call isotime on datetime objects * Support authentication via SAML 2.0 assertions * Fix table name typo in test_sql_upgrade * Cleanup and add more config help strings * Ensure v2 API only returns projects in the default domain * Support for mongo as dogpile cache backend * v3 endpoint create should require url * Fix issue with DB upgrade to assignment table * Remove duplicated cms file * oauth1 extension migration fails with DB2 * Handle exception messages with six.text_type * Remove common.sql.migration * Unimplemented error on V3 get token * Updated from global requirements * Replace assertEqual(None, *) with assertIsNone in tests * Fix keystone-manage db_version * Fix assertEqual arguments order(_ldap_tls_livetest, backend_kvs, etc) * Fix assertEqual arguments order(backend_ldap, cache, v3_protection) * Fix the order of assertEqual arguments(v3_auth, v3_identity) * Move _BaseController to common/controllers.py * Remove oslo rpc * Fix webob.exc.HTTPForbidden parameter miss * Remove redundant default value None for dict.get * Remove oslo notifier * Uses the venv virtualenv for the pep8 command * Sync db.exception from Oslo * Update oslo-incubator log.py to a01f79c * Update man pages * Add tests for create grant when no group * Add tests for create grant when no user * Correct a docstring in keystone.common.config * Enable pep8 test against auto-generated configuration * Update config options with helpstrings and generate sample * Keystone doc has wrong keystone-manage command * Fix assertEqual arguments order * strengthen assertion for unscoped tokens * Remove sql.Base * Always hash passwords on their way into the DB * bad config user_enable_emulation in mask test * Convert Token Memcache backend to new KeyValueStore Impl * Implement mechanism to provide non-expiring keys in KVS * Rationalize the Assignment Grant Tables * Add version routes to KDS * Keystone team uses #openstack-keystone now * Adds model mixin for {to,from}_dict functionality * Adds Cloud Audit (CADF) Support for keystone authentication * Use class attribute to represent 'project' * Switch over to oslosphinx * Replace notifier with oslo.messaging * Clean StatsController unnecesary members * Use global to represent OS-TRUST:trust * Additional notifications for revocations * add policy entries for /v3/regions * Use Oslo.db migration * `find_migrate_repo` improvement * Variable 'domain_ref' referenced before assignment * Cleanup Dogpile KVS Memcache backend support * Fix test_provider_token_expiration_validation transient failure * Restructure KDS options to be more like Keystone's options * Setup code for auto-config sample generation * Correct `find_migrate_repo` usage * Make live LDAP user DN match the default from devstack * Set sensible default for keystone's paste * Treat sphinx warnings as errors * Use WebOb directly in ec2_token middleware * Add lockfile and kombu as requirements for keystone * Move filter_limit_query out of sql.Base * List trusts, incorrect self link * LDAP: document enabled_emulation * Remove s3_token functional tests * Provide clearer error when deleting enabled domain * Remove copyright from empty files * Syncing policy engine from oslo-incubator * Rename Openstack to OpenStack * Refactor get role for trust * KDS fix documented exception * Cleanup oauth tests * Correctly normalize consumer fields on update * Add tests for oauth consumer normalize fields * Adds a fixture for setting up the cache * Clean up database fixtures * Fixes bug in exception message generation * reverse my preferred mailmap * Notifications upon disable * Move identity logic from controller to manager * Changing testcase name to match our terminology * Allow specifying region ID when creating region * explicitly expect hints in the @truncated signature * list limit doc cleanup * Correct error class in find_migrate_repo * Remove unnecessary check to see if trustee exists * Enforce current certificate retrieval behaviour * Use WebOb directly for locale testing * Cleanup KDS doc build errors * Adds rule processing for mapping * Add in functionality to set key_mangler on dogpile backends * Fix indentation issue * Cleanup invalid token exception text * Limit calls to memcache backend as user token index increases in size * Style the code examples in docs as python * Fixes a misspelling * Doc - Keystone configuration - moving RBAC section * Doc - Detailing objects' attributes available for policy.json * Do not use auth_info objects for accessing the API * Remove unused method _get_domain_id_from_auth * Remove unused method _get_domain_conf * Remove unused method _store_protocol * Remove tox locale overrides * Remove unused methods from AuthInfo * Remove unused method _create_metadata * Add test for list project users when no user * Fix assignment KVS backend to not use identity * Update kvs assignment backend docs * Don't skip tests for some bugs * Update oslo-incubator fixture to 81c478 * Remove vim header * revise example extension directory structure * Deprecate s3_token middleware * Update requirements to 661e6 * Implement list limiting support in driver backends * Fix misspellings in keystone * Removes use of fake_notify and fixes notify test * Remove host from per notification options * Document priority level on Keystone notifications * Remove default_notification_level from conf * Mock sys.exit in testing * Remove auth_token middleware doc * Move v3_to_v2_user from manager to controller * Update db.sqlalchemy.session from oslo-incubator 018138 * Adds tcp_keepalive and tcp_keepidle config options * Ensure mapping rule has only local and remote properties * clean up keystone-manage man page * Refactor tests move assertValidErrorResponse * fix grammar error in keystone-manage.rst * Add rules to be a required field for mapping schema * Cleanup docstrings * Do not call deprecated functions * Removes useless string * Removes duplicate key from test fixtures * Fixes a Python3 syntax error using raise * Uses six.text_type instead of unicode * Uses six.iteritems for Python3 compat * Add tests to ensure additional remote properties are not validated * Removes xrange for Python3 compat * Cleanup sample config * Change 'oauth_extension' to 'oauth1_extension' * Modified keystone endpoint-create default region * Load the federation manager * Fix indentation errors found by Pep8 1.4.6+ * Mark strings for translation in ldap backends * Remove unused variable assignment * Sync oslo's policy module * Replace urllib/urlparse with six.moves.* * Change Continuous Integration Project link * Remove legacy diablo and essex test cruft * Refactor Auth plugin configuration options * Use self.opt_in_group overrides * Federation IdentityProvider filter fields on update response * Remove unnecessary test methods * Refactor federation controller class hierarchy * Refactor mutable parameter handling * Avoid use of str() with exceptions * Use message when creating Unauthorized exception * Make error strings translatable * Enhancing tests to check project deletion in Active Directory * Add required properties field to rules schema * Fix assignment to not require user or group existence * deprecate access log middleware * remove access log middleware from the default paste pipeline * deprecate v2.0 API in multiple choice response * cleaned up extension development docs * Add a docstring and rename mapping tests * Remove versionId, versionInfo, versionList from examples * Tests initialize database * Don't set default for a nullable column * Remove autoincrement from String column * Fix docstrings in federation controller * Change assertTrue(isinstance()) by optimal assert * sync oslo-incubator log.py * turn off eventlet.wsgi debug * Make boolean query filter "False" argument work * Fix list_projects_for_endpoint failed bug * Introduce database functionality into KDS * Update the default_log_levels defaults * Correct sample config default log levels * deprecate stats middleware * Use passed filter dict param in core sql filtering * Fix federation documentation reference * build auth context from middleware * correct the document links in man documents * Use six.text_type to replace unicode * Don't mask the filter built-in * Move sql.Base.transaction * Remove sql.Base.get_session * renamed extensions development doc * Implement filter support in driver backends * append extension name to trust notifications * Allow event callback registration for arbitrary resource types * Fix test_auth isolation * Policy sample - Identity v3 resources management * Tests use setUp rather than init * Improve forbidden checks * Tests remove useless config list cleanup code * use assertEqual instead of assertIs for string comparison * Don't configure on import * Fix reading cache-time before configured * Cleanup eventlet setup * Remove unused variables from common.config * Reference dogpile.cache.memcached backend properly * Unify StringIO usage with six.StringIO * Fix typos in documents and comments * Sync oslo strutils.py * Use six.string_types instead of basestring 2014.1.b2 --------- * Use six to make dict work in Python 2 and Python 3 * initialize environment for tests that call popen * Don't duplicate the existing config file list * Implement notifications for trusts * Remove kwargs from trust_api.create_trust * Fixup incorrect comment * Simple Certificate Extension * Add mapping function to keystone * Switch from 400 to 403 on ImmutableAttributeError * Identity Providers CRUD operations * Move KDS paths file * Update comments in test_v3_protection.py * description is wrong in endpoint filter rst doc * Drop unsused "extras" dependency * LDAP Assignment does not support grant v3 API * Adds run_tests.sh cli option to stop on failure * Removes option to delete test DB from run_tests.sh * Removes deprecation warning from run_tests.sh * v3 credentials, ensure blob response is json * Store ec2 credentials blob as json * remove unused LOG * Store trust_id for v3/credentials ec2 keypairs * Refactor context trust_id check to wsgi.Application base class * Implementation of internal notification callbacks within Keystone * Replacing python-oauth2 by oauthlib * Fix using non-default default_domain_id * Enhance auth tests for non-default default_domain_id * KVS support domain as namespace for users * Remove unused member from KVS assignment * Enhance tests for non-default default_domain_id * rename templated.TemplatedCatalog to templated.Catalog * Sync with global requirements * Implements regions resource in 3.2 Catalog API * Reduces memory utilization during test runs * reduce default token duration to one hour * Document running with pdb * Restructure developing.rst * Enable lazy translation * Sync gettextutils from oslo-incubator 997ab277 * derive custom exceptions directly from Exception * Do not append to messages with + * Convert Token KVS backend to new KeyValueStore Impl * Fix sample config external default doc * Documentation cleanup * Make common log import consistent * Remove unused variables * Safe command handling for openssl * Fix external auth (REMOTE_USER) plugin support * Cleanup test_no_admin_token_auth cleanup code * Subclasses of TestCase don't need to reset conf * Cleanup test_associate_project_endpoint_extension * Tests use cleanUp rather than tearDown * Remove netifaces requirement * Clean up fakeldap logging * Resolve oauth dependency after paste pipeline is loaded * Change ListOpt default value from str or None to list * Sync oslo-incubator rpc module * Cleanup from business logic refactor * Introduce basic Pecan/WSME framework for KDS * Don't need session.flush in context managed by session * races cause 404 when removing user from project * initialize eventlet for tests * Flush tokens in batches with DB2 * Remove unnecessary line in test_auth * Clean up docstrings in contrib.oauth1.core * Remove unused test function * Remove 'disable user' logic from _delete_domain_contents * Break dependency of base V3Controller on V2Controller * Move deletion business logic out of controllers * Do not update password when updating grants in Assignment KVS * Cleanup of new credential_api delete methods * Enhance list_group_users in GroupApi * Remove noop code * Remove unused imports * Fix typo in test * Fix IPv6 check * Remove unused code in contrib/ec2/controllers.py * Fix use the fact that empty sequences are false * Imported Translations from Transifex * Synchronized with oslo db and db.sqlalchemy * Fix variable passed to driver module * Updated Keystone development install instructions for Ubuntu * Stops file descriptor leaking in tests * Re-write comment for ADMIN_TOKEN * Reduced parameters not used in _populate_user() * Sync several modules from oslo-incubator * Use oslo.db sessions * Switch to oslo-incubator mask_password * Replace xrange in for loop with range * Move Assignment Controllers and Routers to be First Class * Remove Identity and Assignment controller interdependancies * Policy based domain isolation can't be defined * Moves keystoneclient master tests in a new class * Makes the test git checkout info more declaritive * trustee unable to perform role based operations on trust * Cleanup backend loading * Uses oslo's deprecated decorator; removes ours * Move endpoint_filter extension documentation * Refactor setup_logging * Fixes documentation building * Create user returns 400 without a password * Fixes the v2 GET /extensions curl example in the documentation * Add assertSetEqual to base test class * Base Implementation of KVS Dogpile Refactor * Sync db.sqlalchemy from oslo-incubator * Fix errors for create_endpoint api in version2 * Fix issues handling trust tokens via ec2tokens API * Fix typo in identity:list_role_assignments policy * Debug env for tox * Updated from global requirements * Sync global requirements to pin sphinx to sphinx>=1.1.2,<1.2 * Add ABCMeta metaclass to token provider * token provider cleanup * Sync versionutils from oslo * Cleanup duplication in test_backend * replace "global" roles var names with "all" roles * Remove unused token.valid index * Narrow columns used in list_revoked_tokens sql * Remove roles from OS-TRUST list responses * Remove deprecated code * Sync rpc fix from oslo-incubator * Don't run non-tests * Formalize deprecation of token_api.list_tokens * Add index to cover revoked token list 2014.1.b1 --------- * Refactor assertEqualXML into a testtools matcher * Adds support for username to match the v2 spec * One transaction per call to sql assignment backend * Allow caching to be disabled and tests still pass * Sync From OSLO * Updated from global requirements * Revert "Return a descriptive error message for controllers" * Adds a resource for changing a user's password * Deprecates V2 controllers * Updates .gitignore * Ensure the sample policy file won't diverge * Add pycrypto as a test-requirement * Imported Translations from Transifex * Fix typo in keystone * Added documentation to keystone.common.dependency * Make HACKING.rst DRYer * Allow downgrade for extensions * Try decoding string to UTF-8 on error message fail * Import strutils from oslo * Capture debug logging in tests * Easy testing with alternate keystoneclient * Sync log_handler module from Oslo * refactor test_catalog * PasteConfigNotFound also raised when keystone.conf not found * Style improvements to logging format strings * Sync the DB2 communication error code change from olso * Skip test_arbitrary_attributes_* in _ldap_livetest * Add documentation for Read Only LDAP configuration option * Remove deprecated auth_token middleware * Role NoneType object has no attribute setdefault * Utilites for manipulating base64 & PEM * Add memcache options to sample config * UUID vs PKI docs * RST fix for os_inherit example * Rewrites the serveapp method into a fixture * Allow use of rules Policy driver * Return a descriptive error message for controllers * Proxy Assignment from Identity Deprecated * Remove obsolete redhat-eventlet.patch * AuthInfo use dependency injection * Issue unscoped token if user's default project is invalid * Detangle v3 RestfulTestCase setup * Do not name variables as builtins * Updated from global requirements * Removes unused paste appserver instances from tests * Add WSGI environment to context * trusts raise validation error if expires_at is invalid * Fix newly discovered H302 * test attribute update edge cases * Return an error when a non-existing tenant is added to a user * use different bind addresses for admin and public * Sync log module from oslo * Change deprecated CLI arguments * UserAuthInfo use dependency injection * fix unparseable JSON * Duplicate delete the user_project_metadata * Skip test_create_update_delete_unicode_project in _ldap_livetest * don't rebind stdlib's os.chdir function * Dependency cleanup * Moves common RestfulTestCase to it's own module * proxy removed from identity and changed to assignment * Uses fixtures for mox and stubs * Adds fixture package from oslo * Fix KVS create_grant to not raise NotFound if no user/group * Enhance tests for assignment create_grant when no user or group * Clean up duplicate exceptions in docs for assignment.Driver * Remove obsolete driver test module * Change sample policy files to use policy language * Documentation on how-to develop Keystone Extensions * Allow delete user or group at same time as role * Enhance tests for delete_grant no user/group * Fix issue deleting ec2-credentials as non-admin user * Remove duplicated code on test_v3_auth * Removes NoModule from the base testcase * Fixes tox coverage command * Update mailmap for Joe Gordon * Add WWW-Authenticate header in 401 responses * Use abstract base class for endpoint_filter driver * Use abstract base class for oauth driver * Use abstract base class for policy driver * Use abstract base class for token driver * Document tox instead of run_tests.sh * Update my mailmap * remove 8888 port in sample_data.sh * Adds decorator to deprecate functions and methods * Move fakeldap to tests * Fix remove role assignment adds role using LDAP assignment * Enhance tests for deleting a role not assigned * Implementation of opt-out from catalog data during token validation * Add external.Base class to external plugins * Add notifications for groups and roles * add IRC channel & wiki link to README * Add python-six to requirements * Fix v2 token user ref with trust impersonation=True * Changes to testr as the test runner * Fixes error messaging * Handle unicode at the caching layer more elegantly * set user_update policy to admin_required * Remove unused DEFAULT_DOMAIN variable * Remove unused config option auth_admin_prefix * Remove unused member * Adds tests for user extra attribute behavior * Adds identity v2 tests to show extra behavior * Treats OS-KSADM:password as password in v2 APIs * Adds more uniformity to identity update_user calls * Don't use default value in LimitingReader * Use abstract base class for auth handler * Use abstract base class for catalog driver * Use abstract base class for credential driver * Use abstract base class for assignment driver * Use abstract base class for trust driver * Use abstract base class for identity driver * remove the nova dependency in the ec2_token middleware * Catch the socket exception and log it * Fixes broken doc references * Sync db.sqlalchemy * Handle DB2 disconnect * Fix mysql checkout handler AttributeError * Disable lazy gettext 2013.2.rc1 ---------- * Open Icehouse development * Imported Translations from Transifex * Sync with global requirements * Add tests dir to the coverage omit list * Update tox config * Close the cursor for SQLite for 034 upgrade/downgrade on select * Imports oslo policy to fix test issues * Fixes errors logging in as a user with no password * Fix live LDAP tests * Eliminate type error on search_s * Fix error when create user with LDAP backend * assertEquals is deprecated, use assertEqual (H602) * Validate token calls return 404 on invalid tokens * Protect oauth controller calls and update policy.json * Fix updating attributes with ldap backend * sync oslo policy * Changes v1.1 to v2 for Compute endpoint in sample_data.sh * Update man pages * Update man page version * Sync gettextutils from oslo * only run flake8 once (bug 1223023) * upgrade to oslo.config 1.2 final * Add user to project if project ID is changed * Ensure any relevant tokens are revoked when a role is deleted * Check token_format for default token providers only * Modify oauth1 tests to use generated keystone token in a call * Test for backend case sensitivity * Remove ldap identity domain attribute options * Cleanup of tenantId, tenant_id, and default_project_id * Add extra test coverage for unscoped token invalidation * Monkey patch select in environment * Rewrite README.rst * Enclose command args in with_venv.sh * check for domain existence before doing any ID work * Ensure v2 tokens are correctly invalidated when using BelongsTo * Sync gettextutils from oslo * Use localisation for logged warnings * Fix misused assertTrue in unit tests * oauth using optional dependencies * Rationalize list_user_projects and get_projects_for_user * Optional dependency injection * Include new notification options in sample config * fix rst syntax in database schema migrations docs * Ignore H803 from Hacking * Test upgrade migration 16->17 * test token revocation list API (bug 1202952) * Imported Translations from Transifex * gate on H304: no relative imports * Move gettextutils installation in tests to core * Cleanup tests imports so not relative * Tests use "from keystone import tests" * Reduce churn of cache on revocation_list * domain-specific drivers experimental in havana * Fixes for user response with LDAP user_enabled_mask * Close each LDAP connection after it is used, following python-ldap docs * Remove CA key password from cert setup * Import core.* in keystone.tests * Fix incorrect test for list_users * Changed header from LLC to Foundation based on trademark policies * Changes template header for translation catalogs * Support timezone in memcached token backend 2013.2.b3 --------- * Imported Translations from Transifex * Move CA key from certs directory to private directory * OAuth authorizing user should propose roles to delegate * Need to use _() to handle i18n string messages * Fix the code miss to show the correct error messages * Move _generate_paste_config to tests.core * add 'project' notifications to docs * Implement basic caching around assignment CRUD * Update keystone wsgi httpd script for oslo logging * Utilities to create directores, set ownership & permissions * Modify default file/directory permissions * Add a oauth1-configuration.rst and extension section to docs * Update keystone-all man page * Cleanup cache layer tests * Implement caching for Tokens and Token Validation * Document usage notifications * Imported Translations from Transifex * Remove kvs backend from oauth1 extension * Use joins instead of multiple lookups in groups sql * Add project CRUD to assignment_api Manager * Add Memory Isolating Cache Proxy * Enable SQL tests for oauth * Implement decorator-based notifications for users * Use common db model class from Oslo * Add common code from Oslo for work with database * Use testtools as base test class * Bump hacking to 0.7 * Removes KVS references from the documentation * Add notifications module * Drop support for diablo to essex migrations * Add 'cn' to attribute_list for enabled_users/tenants query * Implement API protection on target entities * Refactor Token Provider to be aware of expired tokens * Implement Caching for Token Revocation List * Keystone Caching Layer for Manager Calls * Create associations between projects and endpoints * Fixes a link in the documentation * Use correct filename for index & serial file when setting permissions * remove flake8 option from run_tests.sh * Fix role lookup for Active Directory * Clean up keystone-manage man page * change oauth.consumer description into nullable * Use system locale when Accept-Language header is not provided * Fix translate static messages in response * Migrating ec2 credentials to credential * Fix error where consumer is not deleted from sql * add foreign key constraint on oauth tables * Remove a useless arg in range() * Remove enumerate calls * filter in ldap list_groups_for_user * Delete file TODO * use provider to validate tokens * Fix isEnabledFor for compatibility with logging * Ensure username passed by REMOTE_USER can contain '@' * fix the default values for token and password auth * Remove an enumerate call * Add defense in ldap:get_roles_for_user_and_project * remove unused function * Remove Keystone specific logging module * remove refs to keystone.common.logging * Remove User Check from Assignments * Refactor Token Providers for better version interfaces * Remove kwargs from manager calls / general cleanup * Store hash of access as primary key for ec2 type * Add delegated_auth support for keystone * Fix LDAP Identity get user with user_enabled_mask * Fix LDAP Identity with non-zero user_enabled_default * More validation in test_user_enable_attribute_mask * Add test test_deleting_project_delete_grants * Cleaned up a few old crufties from README * Clean hacking errors in advance of hacking update * Add unit test to check non-string password support * Assignment to reserved built-in symbol: filter * Implement domain specific Identity backends * Increase length of username in DB * Cleaned up pluggable auth docs * Fix test_user_enable_attribute_mask so it actually tests * Do not skip test_user_enable_attribute_mask in _ldap_livetest * Skip test_create_unicode_user_name in _ldap_livetest * Refactor Keystone to use unified logging from Oslo * Revoke user tokens when disabling/delete a project * Move affirm_unique() in create() to BaseLdap * Move some logic from update() to BaseLdap * Add support for API message localization * Remove unused import * Assignment to reserved built-in symbol: dir * Move 'tests' directory into 'keystone' package * Initial implementation of unified-logging * Sync notifier module from Oslo * Move Babel dependency from test-req to req * Ignore flake issues in build/ directory * update usage in run_test.sh for flake8 * Drop extra credential indexes * Sync models with migrations * Add memcache to httpd doc * Sync unified logging solution from Oslo * Configurable max password length (bug 1175906) * Fix select n+1 issue in keystone catalog * Make pki_setup work with OpenSSL 0.9.x * extension migrations * Create default role on demand * Set wsgi startup log level to INFO * Abstract out attribute_ignore assigning in LDAP driver * Abstract out attribute_mapping filling in LDAP driver * Imported Translations from Transifex * remove swift dependency of s3 middleware * Raise max header size to accommodate large tokens * Clean up use of token_provider manager in tests * add OS-TRUST to links * Run test_mask_password once * Remove kwargs from manager calls where not needed * V3 API need to check mandatory field when creating resources * Use dependency injection for assignment and identity * Handle circular dependencies * Clear out the dependency registry between tests * .gitignore eggs * Handle json data when migrating role metadata * Sync DB models and migrations in keystone.assignment.backends.sql * Remove passwords from LDAP queries * use 'exc_info=True' instead of import traceback * Fix typo: Tenents -> Tenants * Use keystone.wsgi.Request for RequestClass * Update references with new Mailing List location * Scipped tests don't render as ERROR's * Implement exception module i18n support * Remove vestiges of Assignments from LDAP Identity Backend * Load backends before deploy app in client tests * default token format/provider handling * Fixing broken credential schema in sqlite * Use assignment_api rather than assignment * Deprecate kvs token backend * Ec2 credentials table not created during testing * Correct Spelling Mistake * Remove an enumerate call * Load app before loading legacy client in tests * Add [assignment].driver to sample config * Deprecation warning for [signing] token_format * Support token_format for backward compatibility * sql.Driver:authenticate() signatures should match * update requires to prevent version cap * Return correct link for effective group roles in GET /role_assignments * Implement Token Binding * Implemented token creation without catalog response * Fix XML rendering with empty auth payload * Pluggable Remote User * grammar fixes in error messages * Implement role assignment inheritance (OS-INHERIT extension) * Implements Pluggable V2 Token Provider * Register Extensions * Implements Pluggable V3 Token Provider * Mixed LDAP/SQL Backend * Clear cached engine when global engine changes * python3: Introduce py33 to tox.ini * Add version so that pre-release versioning works * Sync-up crypto from oslo-incubator * Add crypto dependency * Imported Translations from Transifex * Change domain component value to org from com * Move temporary test files into tests/tmp * Use InnoDB for MySQL * Rationalize how we get roles after authentication in the controllers * Python 3.x compatible use of print * Regenerate example PKI after change of defaults * assignment backend * wsgi.BaseApplication and wsgi.Router factories should use **kwargs * Add unittest for keystone.identity.backends.sql Models * Imported Translations from Transifex * Do not create LDAP Domains sub tree * Use oslo.sphinx and remove local copy of doc theme * Move comments in front of dependencies * Remove context from get_token call in normalize_domain_id * Fix issue with v3 tokens and group membership roles * Sync install_venv_common from oslo * Remove a useless arg in range() * Remove an enumerate call * Update paths to pem files in keystone.conf.sample * Don't use deprecated BaseException.message * Add callbacks for set_global_engine * Work without admin_token_auth middleware * Implement GET /role_assignment API call * rename quantum to neutron in docs * Install locales for httpd * DB2 migration support * Use event.listen() instead of deprecated listeners kwarg * Add 'application' to keystone.py for WSGI * Remove hard tabs and trailing whitespace * Manager instead of direct driver * check for constraint before dropping * Stop passing context to managers (bug 1194938) * `tox -ecover` failure. Missing entry in tox.ini * Clean up keystone-all.rst * Fix up some trivial license mismatches * Revert environment module usage in middleware * LDAP list group users not fail if user entry deleted * Do not raise NEW exceptions * Move identity ldap backend from directory to file * wsgi.Middleware factory should use **kwargs * Removing LDAP API Shim * Consolidate admin_or_owner rule * Isolate eventlet code into environment * Set default 'ou' name for LDAP projects to Projects * Imported Translations from Transifex * Imported Translations from Transifex * Move user fileds type check to identity.Manager * Http 400 when project enabled is not a boolean * Imported Translations from Transifex * Correct the resolving api logic in stat middleware * Remove a stat warning log * Using sql as default driver for tokens * Correct LDAP configuration doc * Force simple Bind for authentication * Initialize logging from HTTPD * LDAP get_project_users should not return password * Add checks to test if enabled is bool * Fix link typo in Sphinx doc * python WebOb dependency made unpinned * Remove explicit distribute depend * Version response compatible with Folsom * Adds tests for XML version response * Replace openstack-common with oslo in docs * drop user and group constraints * Correct the default name attribute for role * Allow request headers access in app context * Remove how to contribute section in favor of CONTRIBUTING.rst * Fix token purging for memcache for user token index * add ca_key to sample configuration * Commit transaction in migration * Fix internal doc links (bug 1176211) * Missing contraction: Its -> It's (bug 1176213) * Pass on arguments on Base.get_session * Remove bufferedhttp * Move coverage output dir for Jenkins * Check schema when dropping constraints * Import eventlet patch from oslo * Raise key length defaults * Base.get_engine honor allow_global_engine=False * run_tests.sh should use flake8 (bug 1180609) * Ignore the .update-venv directory * Ignore conflict on v2 auto role assignment (bug 1161963) * remove_role_from_user_and_project affecting all users (bug 1170649) * Maintain tokens after role assignments (bug 1170186) * split authenticate call * Add db_version command to keystone-manage * Live SQL migration tests * Fix incorrect role assignment in migration * typo in 'import pydev' statement * Fixes a typo * Imported Translations from Transifex * Improve the performance of tokens deletion for user * Revert "Set EVENTLET_NO_GREENDNS=yes in tox.ini." * Disable eventlet monkey-patching of DNS * Fix the debug statement * Document size limits * Add index on valid column of the SQL token Backend * Add KEYSTONE_LOCALEDIR env variable * Add arg to keystone-manage db_sync 2013.2.b1 --------- * Add index on expires column of the SQL token Backend * fix error default policy for create_project * Require keystone-user/-group for pki_setup * Replace assertDictContainsSubset with stdlib ver * separate paste-deploy configuration from parameters * Add missing oslo module * Convert openstack-common.conf to the nicer multiline format * Rename requires files to standard names * Cleanup docstrings (flake8 H401, H402, H403, H404) * imports not in alphabetical order (flake8 H306) * import only modules (flake8 H302) * one import per line (flake8 H301) * eliminate 'except:' (flake8 H201) * consistent i18n placeholders (flake8 H701, H702, H703) * use the 'not in' operator (flake8 H902) * Use TODO(NAME) (flake8 H101) * Remove unnecessary commented out code * Enumerate ignored flake8 H* rules * Migrate to pbr * Remove unused variables (flake8 F841) * Satisfy flake8 import rules F401 and F403 * Test 403 error title * Imported Translations from Transifex * Remove useless private method * Consolidate eventlet code * Use webtest for v2 and v3 API testing * Add missing space to error msg * Imported Translations from Transifex * Read-only default domain for LDAP (bug 1168726) * Add assertNotEmpty to tests and use it * Implement Token Flush via keystone-manage * get SQL refs from session (bp sql-query-get) * extracting credentials * Move auth_token middleware from admin user to an RBAC policy * Accept env variables to override default passwords * Http 400 when user enabled is not a boolean * Migrate to flake8 * Fix pyflakes and pep8 in prep for flake8 * Allow backend & client SQL tests on mysql and pg * Revert "Disable eventlet monkey-patching of DNS" * Set EVENTLET_NO_GREENDNS=yes in tox.ini * Disable eventlet monkey-patching of DNS * Revoke tokens on user delete (bug 1166670) * A minor refactor in wsgi.py * Skip IPv6 tests for eventlet dns * LDAP list groups with missing member entry * Fix 403 status response * Remove unused CONF.pam.url * Mark LDAP password and admin_token secret * HACKING LDAP * Make migration tests postgres & mysql friendly * Documentation about the initial configuration file and sample data * Add rule for list_groups_for_user in policy.json * Test listing of tokens with a null tenant * fix duplicate option error * Delete extra dict in token controller * What is this for? * Removed unused imports * Remove non-production middleware from sample pipelines * Replace password to "***" in the debug message * Fixed logging usage instead of LOG * Remove new constraint from migration downgrade * Allow additional attribute mappings in ldap * Enable unicode error message * Sync with oslo-incubator copy of setup.py * Set empty element to "" * Fixed unicode username user creation error * Fix token ids for memcached * Use is_enabled() in folsom->grizzly upgrade (bug 1167421) * Generate HTTPS certificates with ssl_setup * Fix for configuring non-default auth plugins properly * test duplicate name * Add TLS Support for LDAP * fix undefined variable * clean up invalid variable reference * Clean up duplicate methods * stop using time.sleep in tests * don't migrate as often * use the openstack test runner * Fix 401 status response * Fix example in documentation * Fix IBM copyright strings * Share one engine for more than just sqlite in-memory * Add missing colon for documentation build steps * Mark sql connection with secret flag 2013.1.rc2 ---------- * Fix test coverage for v2 scoped auth xml response (bug 1160504 * Fix test coverage for v2 scoped auth xml response (bug 1160504) * close db migration session * Use string for port in default endpoints (bug 1160573) * keystone commands don't print any version information * bug 1159888 broken links in rst doc * use the roles in the token when recreating * Sync with oslo-incubator * Rename trust extension (bug 1158980) * Rename trust extension * keystone commands don't print any version information * Imported Translations from Transifex 2013.1.rc1 ---------- * Add a dereference option for ldap * Make versions aware of enabled pipelines * Move trusts to extension * Move trusts to extension * Version bump to 2013.2 * Add a dereference option for ldap * Allow trusts to be optional * Enable emulation for domains * Wrap config module and require manual setup (bug 1143998) * Correct spacing in warning msg * Prohibit V3 V2 token intermix for resource in non-default domain (bug 1157430) * Properly handle emulated ldap enablement * Support for LDAP groups (bug #1092187) * Validate domains unconditionally (bug 1130236) * Fix live ldap tests * V2, V3 token intermix for unscoped tokens (bug 1156913) * Pass project membership as dict in migration 015 * Ensure delete domain removes all owned entities * Utilize legacy_endpoint_id column (bug 1154918) * Test default_project_id scoping (bug 1023502) * Fix XML handling of member links (bug 1156594) * Discard null endpoints (bug 1152632) * extracting user and trust ids into normalized fields * No parent exception to wrap * Remove duplicate password/token opts * xml_body returns backtrace on XMLSyntaxError * duplicated trust tests * Migrate roles from metadata to user_project_metadata * Fixes bug 1151747: broken XML translation for resource collections * Revise docs to use keystoneclient.middleware.auth_token * quiet route logging on skipped tests * Ensure tokens are revoked for relevant v3 api calls * Remove un-needed LimitingReader read() function * Catch and log server exceptions * Added test cases to improve LDAP project testing * Switch to final 1.1.0 oslo.config release * Filter out legacy_endpoint_id (bug 1152635) * Improve tests for api protection and filtering * add belongs_to check * Revert "update tests/__init__.py to verify openssl version" * Revert "from tests import" * Make Keystone return v3 as part of the version api * Run keystone server in debug mode * remove spurious roles check * bug 1133526 * Fix folsom -> grizzly role table migration issues (bug 1119789) * Delete tokens for user * from tests import * v3 endpoints won't have legacy ID's (bug 1150930) * return 201 Created on POST request (bug1131119) * add missing attributes for group/project tables (bug1126021) * Remove unused methods from LDAP backed * Move get_by_name to LdapBase * fix typo in kvs backend * mark 2.0 API as stable * unable to load certificate should abort request * Move auth plugins to 'keystone.auth.plugins' (bug 1136967) * Change exception raised to Forbidden on trust_id * cleanup trusts in controllers * remove unused import * ports should be ints in config (bug 1137696) * Expand v3 trust test coverage * Trusts * bug 1134802: fix inconsistent format for expires_at and issued_at * Sync timeutils with oslo * Straighten out NotFound raising in LDAP backend * residual grants after delete action (bug1125637) * Remove TODO that didn't land in grizzly * Make getting user-domain roles backend independant * Explain LDAP page_size & default value * Imported Translations from Transifex * Enable a parameters on ldap to allow paged_search of ldap queries This fixes bug 1083463 * update tests/__init__.py to verify openssl version * command line switch for short pep8 output * Convert api to controller * bug 1131840: fix auth and token data for XML translation * flatten payload for policy * Unpin pam dependency version * keystone : Use Ec2Signer utility class from keystoneclient * Move handle_conflicts decorator into sql * domain_id_attributes in config.py have wrong default value * Rework S3Token middleware tests * Remove obsolete *page[_marker] methods from LDAP backend * Setup logging in keystone-manage command * Ensure keystone unittests do not leave CONF.policyfile in bad state * catch errors in wsgi.Middleware * Fix id_to_dn for creating objects * Tests for domain-scoped tokens * domain-scoping * Pass query filter attributes to policy engine * Removed redundant assertion * v3 token API * Update oslo-config version * Correct SQL migration 017 column name * merging in fix from oslo upstream * enabled attribute emulation support * Change the default LDAP mapping for description * Ensure user and tenant enabled in EC2 * Disable XML entity parsing * Remove old, outdated keystone devref docs * Update the Keystone policy engine to the latest openstack common * Implement name space for domains * Update sample_data.sh to match docs * project membership to role conversion * Remove test_auth_token_middleware * Workaround Migration issue with PostgreSQL * make LDAP query scope configurable * make fakeldap._match_query work for an arbitrary number of groups * Use oslo-config-2013.1b3 * Remove usage of UserRoleAssociation.id in LDAP * Add an update option to run_tests.sh * Add pysqlite as explicit test dep * fix unit test when memcache middleware is not configured * add missing kvs functionality (bug1119770) * Update to oslo version code * adding additional backend tests (bug1101244) * Fix spelling mistakes * Cleaned up keystone-all --help output * Keystone backend preparation for domain-scoping * Use install_venv_common.py from oslo * Spell accommodate correctly * Missed import for IPv6 tests skip * Add missing log_format, log_file, log_dir opts * Fix normalize identity sql ugrade for Mysql and postgresql * remove duplicate model declaration/attribution * simplify query building logic * Fix test_contrib_s3_core unit test * Expand dependency injection test coverage * remove unneeded config reloading (it's already done during setUp) * allow unauthenticated connections to an LDAP server * Relational API links * return 400 Bad Request if invalid params supplied (bug1061738) * UserApi.update not to require all fields in arg * Tenant update on LDAP breaks if there is no update to apply * Query only attributes strictly required for keystone when using it with existing LDAP servers * Update .coveragerc * Add size validations to token controller * add check for config-dir parameter (bug1101129) * Silence routes internal debug logging * Imported Translations from Transifex * Delete Roles for User and Project LDAP * Why .pop()'ing urls first is important * don't create a new, copied list in get_project_users * Fixes 'not in' operator usage * Add --keystone-user/group to keystone-manage pki_setup * Adds png versions of all svg image files. Changes reference * Updates migration 008 to work on PostgreSQL * Create a default domain (bp default-domain) * Generate apache-style common access logs * import tools/flakes from oslo * tenant to project in the apis * Tenant to Project in Back ends * Fix bugs with set ldap password * Enable/disable domains (bug 1100145) * Readme: use 'doc' directory not 'docs' * rename tenant to project in sql * Update to requests>=1.0.0 for keystoneclient * Fix pep8 error * Document user group LDAP options * Sync latest cfg from oslo-incubator * Limit the size of HTTP requests * Fix role delete method in LDAP backend * public_endpoint & admin_endpoint configuration * Skip IPv6 tests if IPv6 is not supported * Allow running of sql against the live DB * Test that you can undo & re-apply all migrations * downgrade user and tenant normalized tables downgraded such that sqlite is supported, too * Auto-detect max SQL migration * Safer data migrations * Sync base identity Driver defs with SQL driver * Fix i18n of string templates * Enhance wsgi to listen on ipv6 address * add database string field length check * Autoload schema before creating FK's (bug 1098174) * Enable exception format checking in the tests * reorder tables for delete * Validated URLs in v2 endpoint creation API * Fixes import order nits * Cleanup keystoneclient testing requirements * Fix issue in test_forbidden_action_exposure * Correct spelling errors / typos in test names * Update ldap exceptions to pass correct kwargs * Add _FATAL_EXCEPTION_FORMAT_ERRORS global grizzly-2 --------- * Keystone server support for user groups * Add missing .po files to tarball * Imported Translations from Transifex * adds keyring to test-requires * Revert "shorten pep8 output" * Upgrade WebOb to 1.2.3 * il8n some strings * Imported Translations from Transifex * Removed unused variables * Removed unused imports * Add pyflakes to tox.ini * Fix spelling typo * shorten pep8 output * Driver registry * Adding a means to connect back to a pydevd debugger * add in pip requires for requests * Split endpoint records in SQL by interface * Fix typo s/interalurl/internalurl/ * module refactoring * Test for content-type appropriate 404 (bug 1089987) * Imported Translations from Transifex * fixing bug 1046862 * Expand default time delta (bug 1089988) * Add tests for contrib.s3.core * Test drivers return HTTP 501 Not Implemented * Support non-default role_id_attribute * Remove swift auth * Move token controller into keystone.token * Import pysqlite2 if sqlite3 is not available * Remove mentions of essex in docs (bug 1085247) * Ensure serviceCatalog is list when empty, not dict * Adding downgrade steps for migration scripts * Port to argparse based cfg * Only 'import *' from 'core' modules * use keystone test and change config during setUp * Bug 1075090 -- Fixing log messages in python source code to support internationalization * Added documentation for the external auth support * check the redirected path on the request, not the response * Validate password type (bug 1081861) * split identities module into logical parts remove unneeded imports from core * Ensure token expiration is maintained (bug 1079216) * normalize identity * Fixes typo in keystone setup doc * Imported Translations from Transifex * Stop using cfg's internal implementation details * syncing run_tests to match tox grizzly-1 --------- * Expose auth failure details in debug mode * Utilize policy.json by default (bug 1043758) * Wrap v3 API with RBAC (bug 1023943) * v3 Identity * v3 Catalog * v3 Policies * Import auth_token middleware from keystoneclient * Imported Translations from Transifex * Refix transient test failures * Make the controller addresses configurable * Expose authn/z failure info to API in debug mode * Refactor TokenController.authenticate() method * Fix error un fixtures * Ensures User is member of tenant in ec2 validation * Properly list tokens with a null tenant * Reduce total number of fixtures * Provide config file fields for enable users in LDAP backend (bug1067516) * populate table check * Run test_keystoneclient_sql in-memory * Make tox.ini run pep8 checks on bin * tweaking docs to fix link to wiki Keystone page * Various pep8 fixes for keystone * Use the right subprocess based on os monkeypatch * Fix transient test failures (bug 1077065, bug 1045962) * Rewrite initial migration * Fix default port for identity.internalURL * Improve feedback on test failure * fixes bug 1074172 * SQL upgrade test * Include 'extra' attributes twice (bug 1076120) * Return non-indexed attrs, not 'extra' (bug 1075376) * bug 1069945: generate certs for the tests in one place * monkeypatch cms Popen * HACKING compliance: consistent use of 'except' * auth_token hash pki key PKI tokens on hash in memcached when accessed by auth_token middelware * key all backends off of hash of pki token * don't import filter_user name, use it from the identity module * don't modify the passed in dict to from_dict * move hashing user password functions to common/utils * ignore .tox directory for pep8 in runtests * Imported Translations from Transifex * Implements REMOTE_USER authentication support * pin sqlalchemy to 0.7 * Move 'opentack.context' and 'openstack.params' definitions to keystone.common.wsgi * Removes duplicate flag for token_format * Raise exception if openssl stderr indicates one * Ignore keystone.openstack for PEP8 * Fixed typo in log message * Fixes 500 err on authentication for invalid body * Enable Deletion of Services with Endpoints * Exception.message deprecated in py26 (bug 1070890) * Utilize logging instead of print() * stop LdapIdentity.create_user from returning the user's password * Compare token expiry without seconds * Moved SQL backend tests into memory * Add trove classifiers for PyPI * Adding handling for get user/tenant by name * Fixed bug 1068851. Refreshed new crypto for the SSL tests * move filter_user function to keystone.identity.core * Fixes response for missing credentials in auth * making PKI default token type * Fixes Bug 1063852 * bug 1068674 * Update common * Extract hardcoded configuration in ldap backend (bug 1052111) * Fix Not Found error, when router not match * add --config-dir=DIR for keystone-all option * Add --config-dir=DIR in OPTIONS * Delete role does not delete role assignments in tenants (bug 1057436) * replacing PKI token detection from content length to content prefix. (bug 1060389) * Document PKI configuration and management * Raise if we see incorrect keyword args "condition" or "methods" * Filter users in LDAP backend (bug 1052925) * Use setup.py develop to insert code into venv * Raise 400 if credentials not provided (bug 1044032) * Fix catalog when services have no URL * Unparseable endpoint URL's should raise friendly error * Configurable actions on LDAP backend in users Active Directory (bug 1052929) * Unable to delete tenant if contains roles in LDAP backend (bug 1057407) * Replaced underscores with dashes * fixes bug 1058429 * Command line switch for standard threads * Remove run_test.py in favor of stock nose * utf-8 encode user keys in memcache (bug 1056373) * Convert database schemas to use utf8 character set * Return a meaningful Error when token_id is missing * Backslash continuation cleanup * notify calling process we are ready to serve * add Swift endpoint in sample data * Updated Fix for duplicated entries on LDAP backend for get_tenant_users * Fix wsgi config file access for HTTPD * Bump version to 2013.1 folsom-rc1 ---------- * Limit token revocation to tenant (bug 1050025) * Fixed trivally true tests (bug 983304) * add Quantum endpoint in sample data * Add XML namespace support for OSADM service api * Delete user tokens after role grant/revoke * LDAP backend attribute fixes * Document memcached host system time configuration * Implementation of tenant,user,role list functions for ldap * Initialize Metadata variable * Cleanup PEP8 errors from Common * List tokens for memcached backend * Implement token endpoint list (bug 1006777) * Ignore eclipse files * Identity API v3 Config, Routers, Controllers * Sync some misc changes from openstack-common * Sync latest cfg from openstack-common * Remove id_hash column * LOG.warn all exception.Unauthorized authentication failures * Fixed: test_default_tenant_uuid_token not running * Upgrade PEP8 to 1.3.3 (bug 1037303) * Expand PEP8 coverage to include docs & tests * Removed/fixed unused variable references * HACKING compliance & staticly init module vars * PEP8 fix E251 * PEP8 fix * Removed unused imports * Check for expected cfg impl (bug 1043479) * Fixed typos in comment * HACKING: Import by full module path * HACKING: Use single quotes * mistake in doc string * pep8 1.3.3 cleanup removing unused imports * Removed dead code * Fix auth_token middleware to fetch revocation list as admin * Require authz to update user's tenant (bug 1040626) * Code cleanup in doc/source/conf.py * Typo fix in keystone: existant => existent * allow middleware configuration from app config * PEP8 fix for PAM test * change verbose and debug to Fasle in keystone.conf.sample * add token_format=UUID to keystone.conf.sample * Demonstrate that authenticate() returns roles * Add nosehtmloutput as a test dependency * Less information returned with IntegrityError * Support running the tests in the debugger * Removed stray print statement (bug 1038131) * Remove unused variables * PKI Token revocation * Remove unused imports * Adding missing files to MANIFEST.in * Simplify the sql backend deletion of users and tenants * Add tests for PAM authentication * Allow overloading of username and tenant name in the config files * Enabling SQL Catalog tests (bug 958950) * Use user home dir as default for cache * Set example key_size to 1024 * Log errors when signing/verifying * Implement python version of migration 002 * Set default signing_dir based on os USER * Assert adminness on token validation (bug 1030968) * Test for Cert by name * Typo error in keystone/doc/source/configuration.rst * fix broken link * Cryptographically Signed tokens * Sync jsonutils from openstack-common * Added user name validation. Fixes bug 966251 * Import ec2 credentials from old keystone db * Debug output may include passwords (bug 1004114) * Raise unauthorized if tenant disabled (bug 988920) * Files for Apache-HTTPD * Implementation of LDAP functions * Fix the wrong infomation in keystone-manage.rst * Webob needs body to calc Content-Length (bug 1016171) * Prevent service catalog injection in auth_token * Admin Auth URI prefix * updating testing documentation * adding keystoneclient test * Removed redundant / excessively verbose debug * Making docs pretty! * Adding user password setting api call * Fixing pep8 errors in tests/*py * Make sure user dict has id key before checking against it * pep8 for openssl * Run pep8 for tests * Move monkey patch to keystone-all startup * Use sdist tarball instead of zipball * Return a 409 error when adding a second time a role to user/tenant * notify calling process we are ready to serve folsom-2 -------- * Set iso8601 module as default dependence * Fixed user-only role deletion error * Use PyPI for keystoneclient * keystone_manage certificate generation * documenting models * Reorder test imports by full import path * pep8 v1.3.3 compliance (bug 1019498) * Correct Tree DN * don't assume that the LDAP server require authentication * fix variable names to coincide with the ones in common.ldap * Keystone should use openstack.common.timeutils * Fixed marker & limit computation (bug 1006055) * Do not crash when trying to remove a user role (without a tenant) * Keystone should use openstack.common.jsonutils * Refactor 404's into managers & drivers (bug 968519) * fix sphinx warnings * fix man page build * Utilize newer changes in openstack-common * Add .mailmap file * setting up babel for i18n work blueprint start-keystone-i18n * Removed unused import * Fix order of returned tuple elements in pam authenticate * Reorder imports by full module path * Pass serviceCatalog in auth_token middleware * Fixed typo in routing conditions (bug 1006793) * 400 on unrecognized content type (bug 1012282) * Basic request stats monitoring & reporting * Monkey patching 'thread' * Speed up SQL unit tests * PEP8 fixes * Clean up test requires a bit * Use cfg's new global CONF object * Add s3 extension in keystone.conf sample * Tweak for easier, safer subclassing * Revert file mode to be non-executable * fix importing of optional modules in auth_token * Carrying over token expiry time when token chaining * Keystone should use openstack.common.importutils * Require authz for user role list (bug 1006815) * Require authz for service CRUD (bug 1006822) * PEP8 fixes * Use cfg's new behavior of reset() clearing overrides * Use cfg's new group autocreation feature * Sync with latest version of openstack.common.cfg * blueprint 2-way-ssl * Fixes some pep8 warning/errors * Update swift_auth documentation * Add ACL check using : format * Use X_USER_NAME and X_ROLES headers folsom-1 -------- * Allow other middleware overriding authentication * Backslash continuation removal (Keystone folsom-1) * Remove service_* from authtoken examples * Nail prettytable test dependency at 0.5.0 * Invalidate user tokens when a user is disabled * Fix depricated /users/{user-id}/roles * Changed arguments in keystone CLI for consistency * Add validations of 'name' field for roles, users and tenants * Added 'NormalizingFilter' middleware * One 'ctrl-c' kills keystone * Make sure we parse delay_auth_decision as boolean * Flush tenant membership deletion before user * notify calling process we are ready to serve * Invalidate user tokens when password is changed * Added tenant name validation. Fixes bug 966249 * Corrects url conversion in export_legacy_catalog * Truly handle mailmap entries for all combinations * fix pam admin user case * Improve the sample keystone.conf * Add defaults for ldap options * Sync to newer openstack-common * Set defaults for sql options * Set defaults for port options * Add defaults for driver options * Use ConfigOpts.find_file() to locate catalog template * Use ConfigOpts.find_file() to locate policy.json * Policy doc updates; RST syntax consistency * Removed SimpleMatch 'shim'; updated readme * Removed old sections; improved syntax consistency * cleanup dependent data upon user/tenant deletion * Update tests to run servers on 127.0.0.1 * Switch to 1000 rounds during unit tests * Fix argument name referred in the document * Exit on error in a S3 way * Auto generate AUTHORS file for keystone component * Misnamed exception attribute (bug 991936) * Avoid ValueError in 12.04 essex pkg (bug 988523) * Non-nullable User, Tenant, Role names (bug 987121) * Fix expired token tests * Make run_tests.py non-executable * Add distribute to test-requires * Makes the ldap backend return proper role metadata * cleanup no_meta user in live LDAP test * Add ChangeLog to tarball * Fix "it's" grammar errors * Rename keystone.conf to .sample * Import latest openstack-common * Stub out swift log configuration during testing * Remove tenant membership during user deletion * Add a _ at the end of reseller_prefix default * additional logging to support debugging auth issue * Add support to swift_auth for tokenless authz * Make import_nova_auth only create roles which don't already exist * don't duplicate the extra dict in extra * Fix looking for config files * endpoint-crud 404 (bug 963056) * user-role-crud 404 (bug 963056) * ec2-credential-crud 404 (bug 963056) * service-crud 404 (bug 963056) * user-crud 404 (bug 963056) * tenant-crud 404 (bug 963056) * Add build artifacts missing from .gitignore * Switch keystone.test.TestCase to use unittest2 * Raise keystone.exception for HTTP 401 (bug 962563) * Fixed misc errors in configuration.rst * Docs: SQL-based vs File-based Service Catalog * Improve service CRUD test coverage * Change default catalog driver to SQL; doc the options * Replace tabs with spaces * role-crud 404 (bug 963056) * Improve swift_auth test coverage + Minor fixes * Open Folsom essex-rc1 --------- * S3 tokens cleanups * Check values for EC2 * Fix critical typo in endpoint_create (bug 961412) * updating docs to include creating service accts * unique role name constraint * Add test for swift middleware * Spring cleaning, fix PEP8 violations * Rename tokenauth to authtoken * pass the arguments in when starting keystone-all * fix keystone-all's usage of options vs conf * Wrapped unexpected exceptions (bug 955411) * Changing belongsTo validation back to ID * Clean up sql connection args * Improved file logging example (bug 959610) * Swift middleware doc update * Fixes LP #954089 - Service list templated catalog * Remove nova-specific middlewares * Add check for MAX_PASSWORD_LENGTH to utils * Remove glance_auth_token middleware * Support PyPAM in pam backend, update to latest API * Fix default port for identity.internalURL * Installing keystone docs * Update username -> name in token response * Refactor keystone.common.logging use (bug 948224) * Add automatically generated code docs * Properly return 501 for unsupported Catalog calls * docstring cleanup to remove sphinx warnings * updating documentation for rewrite of auth_token * Allow connect to another tenant * Update docs for keystone client cli args * Raising unauthorized instead of 500 (bug 954547) * Failing to update tenants (bug 953678, bug 954673) * added LDAP section to architecture and architecture * Bug #943031 MySQL Server has gone away added docnotes of error messages caught for mysql and reference * making all use of time follow datetime.utcnow() fixes bug 954057 * Improved legacy tenancy resolution (bug 951933) * sample_data.sh: check file paths for packaged installations * Fix iso8601 import/use and date comparaison * Fix double-quoted service names * Remove Nova Diablo reference from migrate docs * Fixes the cli documentation of user/tenant/roles * Add simple set of tests for auth_token middleware * update documention on changing user password * enables run_test option to skip integration * Add token caching via memcache * Update get_metadata to return {} * Diablo to Essex migration docs (bug 934328) * Added license header (bug 929663) * Add AUTHORS to the tarball * create service endpoints in sample data * Fix EC2 credentials crud after policy backend change * port common policy code to keystone * rename belongs_to to belongsTo as per the API spec * Make sure we have a port number before int it * fixes lp#949648 change belongsTo validate to name * HTTP_AUTHORIZATION was used in proxy mode * fix Nova Volume Service in sample data * fixes bug lp#948439 belongs_to and serviceCatalog behavior * removing belongs_to as a kwarg and getting from the context * adding a serviceCatalog for belongs_to calls to tokens * adding test to validate belongs_to behavior in tokens * Make bind host configurable * add more default catalog templates * Fix coverage jobs for Jenkins * Improve auth_str_equal() * Set default identity driver to sql (bug 934332) * Renamed sqlite files (bug 944951) * Isolating backtraces to DEBUG (bug 947060) * updating readme to point to developer setup docs * fixes bug 945274 * Add reseller admin capability * Remove trailing whitespaces in regular file * LDAP get_user_by_name * Added missing import (bug 944905) * add git commit date / sha1 to sphinx html docs * gitignore follow up for docs/ rename * improve auth_token middleware * Add service accounts to sample_data.sh * standardize ldap and related tests * Align with project configs * Fixes doc typo s/SERVIVE/SERVICE/ * Use constant time string comparisons for auth essex-4 ------- * Unpythonic code in redux in auth_token.py * fix pep8 * GET /v2.0 (bug 930321) * LDAP member defaults * Handle KeyError in _get_admin_auth_token * Align tox jobs with project standards * renaming pip-requires-test to test-requires * Provide request to Middleware.process_response() * Add Vary header (bug 928057) * Implement a Catalog SQL backend * Set tenantName to 'admin' in get_admin_auth_token * LDAP Identity backend * Implements extension discovery (bug 928054) * Support unicode in the keystone database * Add HEAD /tokens/{token_id} (bug 933587) * XML de/serialization (bug 928058) * fleshing out architecture docs * Update auth_token middleware so it sets X_USER_ID * Adds AUTHORS file generated from git log (and de-duplicated) * The default nova compute port is 8774 * Fix case of admin role in middleware * Fix MANIFEST.in to include missing files * Remove extraneous _validate_claims() arg * Create tools/sample_data.sh * Backslash continuations (Keystone) * Correct config name for max_pool_size * Use cfg's new print_help() method * Move cfg to keystone.openstack.common * Remove cfg dict mixin * Update cfg from openstack-common * Fix copyright dates and remove duplicate Apache licenses * some additional style bits * Add migration path for Nova auth * fix the style guide to match the code * Re-adds admin_pass/user to auth_tok middleware * Fix thinko in keystone-all sys.path hack * Removing broken & redundant code (bug 933555) * Return HTTP 401 bad user/password is specified * cli now returns an exit status cmd is invalid * Ignore sqlite.db files * Implements admin logic for tenant_list call * Implemented get_tenant_users. Fixed bug 933721 * Removing unused imports from keystone.cli * Set include_package_data=True in setup.py * Remove data_files section from setup.py * Update Manifest.in * Add migrate.cfg to data_files in setup.py * Should return 300 Multiple Choice (bug 925548) * Admin version pipeline not utilized (bug 925548) * fixes #934459 * Fix logging.config import * backport some asserts * remove pycli * Adds missing argument to add_user_to_tenant in create_user * Fixes a failure caused by a recent change to user update in the client * remove executable bit from setup.py * Raising 'NotImplmented' results in TypeError * Update docs for Swift and S3 middlewares * Added Apache 2.0 License information * Add docs on keystone_old -> ksl migration * Add token expiration * Update docs to for current keystone-manage usage * add catalog export * Handle unicode keys in memcache token backend * make sure passwords work after migration * add legacy diablo import tests * change password hash * add essex test as well * add sql for import legacy tests * add import legacy cli command * add migration from legacy db * remove keystoneclient-based manage commands * Remove executable bit from auth_token.py * Update swift token middleware * Add s3_token * Add pagination to GET /tokens * Fixes role checking for admin check * Fix webob exceptions in test_middlware * Add tests for core middleware * Add version description to root path * Add TokenNotFound exception * remove diablo tests, they aren't doing much * Fix largest memory leak in ksl tests * Add memcache token backend * Friendly JSON exceptions (bug 928061, bug 928062) * Fix comment on bcrypt and avoid hard-coding 29 as the salt length * Add SQL token backend * Add content-type to responses * Cope with unicode passwords or None * Add auth checks to ec2 credential crud operations * termie all the things * example in hacking was incorrect * Ensures duplicate users and tenants can't be made * make pip requires match nova * fixes lp:925721 adds .gitreview for redux branch * remove novaclient, fix python syntax * We don't need all the deps to check pep8 * remove extra line * Make ec2 auth actually work * fixing grammar, noting broken enable, adding hacking with prefs for project * Removed unused reference * adding a token service Driver to define the interface * Added support for DELETE /tokens/{token_id} * Fixes bug 924391 * ran through all commands to verify keywords against current (master) keystonelight * updating docs: * Fix "KeyError: 'service-header-mappings'" * updating tox.ini with test pip requirements * use our own logging module * Update auth_token middleware to support creds * Removes nova middleware and config from keystone * minor docstring update for new locations * Missed one more keystone-server * Renamed keystone-server to keystone-all based on comments in LP: #910484 * be more safe with getting json aprams * skip the two tests where testing code is failing * accept POST or PUT for tenant update * deal with reparsing the config files * don't automatically parse sys.argv for cfg * deal with tags in git checkout * fix keystoneclient tests * add tests for essex and fix the testing framework * Update docs/source/developing.rst * Change the name of keystone to keystone-server so the binaries dont conflict with python-keystoneclient * Normalize build files with current jenkins * Use gerrit instead of github * Fix pep8 violations * Add .gitreview file * Added keystone-manage list_role_grants (bug 923933) * removing unused images, cleaning up RST in docstrings from sphinx warnings * pep8 cleanup * shifting contents from _static to static * adding in testing details * moved notes from README.rst into docs/architecture.rst * updating formating for configuration page * format tweaks and moving old docs * shifting older docs into old/ directory * doc updates * moving in all the original docs from keystone * adding python keystoneclient to setup.py deps * fixing up PIP requirements for testing and virtualenv * indents * Make it as a subclass * Added shortcut for id=NULL queries (bug 916386) * fix style and termie's comments about comments * invalid params for roles.delete * initial stab at requiring adminness * Simplify code * add tests that auth with tenant user isn't member of * Add s3tokens validation * Test coverage for issue described in bug 919335 * Removing __init__ from non-packages (bug 921054) * add instructions for setting up a devenv on openSUSE 11.4 and 12.1 * Documented race condition (bug 921634) * Fix race in TestCreateTokenCommand (bug 921634) * Forgot to update models (bug 885426) * Updating example glance paste config * add a bunch of basic tests for the cli * Migrated 'enabled' int columns to bool for postgres (bug 885426) * remove this useless catalog * move cli code into a module for testing * Updated bp keystone-configuration for bp keystone-manage2 * Return Version and Tenant in Endpoints * Updated error message for keystone-manage2 * allow class names to be different from attr names * add ec2 credentials to the cli * fix middleware * Added: "UserWithPassword" Added: "UserWithOnlyEnabled" Removed: "UserWithOnlyPassword" * Update Extended Credentials (EC2, S3) * Fix for bug 921126 * Adds keystone auth-n/auth-z for Swift S3 API * Implement cfg.py * bcrypt the passwords * fix token vs auth_token * Implement Secure Token Auth * some quick fixes to cli, tests incoming * fix pep8 * fix some more pass-by-reference bugs * strip password before checking output * flip actual and expected to match common api * don't allow disabled users to authenticate * turn off echo * fix invalid_password, skip ec2 tests * Suppressed backtraces in tests causes sweaty eyes * strip password from sql backend * raise and catch correct authenticate error * rely on internal _get_user for update calls * Fixed: Inserting URLs into endpoint version attr * strip password from kvs backend * fix user_get/user_list tests * Release Notes for E3 * Addresses bug 918608 * Restore Console Info Logging - bp keystone-logging * removing the sphinx_build from setup.py, adding how to run the docs into the README * Added Vary header to support caching (bug 913895) * Implemented subparsers (bp keystone-manage2) * Handle EC2 Credentials on /tokens * ec2 docs * simple docstrings for ec2 crud * Fixed PEP8 violations and disallowed them * Implemented bp keystone-manage2 * Fixes 918535: time not properly parsed in auth_token middleware * Use dateutil 1.5 * get docs working * some cli improvements * add checks for no password attribute * Prestage fix - fixed requirement name; python-dateutil, not dateutil * users with correct credentials but disabled are forbidden not unauthorized * Pre-staging pip requires * shimming in basics from original keystone * test login fails with invalid password or disabled user * doctry * use token_client in token tests * remove duplicate pycli from pip-requires * fix ec2 sql config * get_client lets you send user and tenant * update how user is specified in tests * rename ec2 tests to be more explicit * use the sql backend for ec2 tests * more failing ec2 tests * add METADATA for boo * add (failing) tests for scoping ec2 crud * add some docs that got overwritten last night * Bug #916199: keystone-manage service list fails with AttributeError on Service.description * Exception raise error * Updates to middleware to deprecate X_USER * Revert "Exception raise error" * fix pep8 * update tests * update some names * fix some imports * split up sql backends too * split up the services and kvs backends * establish basic structure * add docs for various service managers * expect sphinx sources to be autogenned * some tiny docs * fix sphinx * testing rst on github * updating dependencies for ksl * needed to do more for cli opts * make a main in keystone-manage * fix pep8 error * rename apidoc to autodoc * Fix typo * Fix LDAP Schema Syntax (bug 904380) * return to starting directory after git work * spacing * tests for ec2 crud * add keystoneclient expected format * add sql backend, too * add an ec2 extension * update readme * Exception raise error * re-indent * re-indent * re-indent * re-indent kvs.py * re-indent test.py * remove models.py * add some docs to manager * dynamic manager classes for now * add a couple more tests * Bug #915544: keystone-manage version 1 commands broken when using flags * add some more todos * strip newlines * TODO * add role refs to validate token * fix token auth * check for membership * flush that sht * add more middleware * fixing WatchedFileHandler * logging to debugging by default for now * add a noop controller * woops * add glance middleware ?? * add legacy middleware * fix setup.py * adding #vim to file with changed indent * add id-only flag to return IDs * rename ks to keystone-manage * fixing imports for syslog handlers and gettext * adding gettext * adding logging from configuration files, default logging per common * cli using keystoneclient * add a db_sync command to bin/ks, remove others * merge test and default configs * adding project to keystone config to find default config files * some more config in bin/keystone * in the bin config too * rename many service parts to public * keystone_compat -> service * remove keystone from names, remove service * remove default configuration * basic service running again * rename extras to metadata * version number in setup.py * add basic sphinx doc bits * remove references to keystone light * renaming keystonelight to keystone * keystoneclient tests working against sql backend * run all teh keystoneclient tests against sql too * move everything over to the default config * config system overhaul * add nova's cfg framework * fix pep8 * missed a file * most tests working again * still wip, got migration mostly working * get the sql ball rolling, still wip * add sql backend, WIP * Show useful traceback if manage command fails * Fix minor typo * Add 'tenants' to Auth & Validate Response * Fixed Test Coverage Handling * Adding prettytable dependency * Front-end logging * tweaking for running regular tests in jenkins * Implement Role Model * xsd fixes * Added decorators for admin and service_admin checks * Initial keystone-manage rewrite (bp keystone-manage2) * Correct endpoint template URLs in docs * fix bug lp:843064 * finished up services stuff * add the various role tests * add list users * get user tests working * Remove install_requires processing * get endpoints test working * get tenant_add_and_remove_user test working * tenant test working again * copy over the os-ksadm extension * Implement Endpoint, Endpoint Template, and Credential Managers * PEP8 keystone cleanup * Changes run_tests.sh to also run pep8 by default * example crud extension for create_tenant * Updates to Tests/Testing * Un-pythonic methods lp:911311 Fixed pep8 problems Changed comments to docstrings * get some tests working again * merge fixes * fixup * Made tests use both service and admin endpoints * All tests but create_tenant pass * Split keystone compat by admin and service endpoints * Install a good version of pip in the venv * fix bug lp:910491 option "service_host" in keystone.conf not works * Added broken tests to show compatibility gaps * Added tox.ini file * Split keystone compat by admin and service endpoints * Implement Service Manager * Implement Tenant Manager * Fixes bug lp:910169 - Tests are using too much memory Added super() call to tearDown() method * Changed the call to create the KeystoneContextMiddleware object to pass the correct glance ConfigOpts object * Added logging on core modules * Adding logging to Auth-Token Middleware * Implement Role Manager * Refactor models and backends * Add HP-IDM extension to fix Bug 890411 * Move URL Normalizer to Frontends * move novaclient tests over also * clean up test_identity_api * clean up keystoneclient setup * Move Global Role variables out of backendutils * Bug #909255: Endpoint handling broken on SQL backend by portable-identifiers changes * add role crud * speed up tests * add basic fixture functionality * documentation driven development * novaclient now requires prettytable * Return Endpoint IDs * Correct Handling of Default Tenant * Fix duplicate logging * Added global endpoints response in XML as well * Fix: Client and Unit Tests not correctly failing a build * Bug #907521. Changes to support get roles by service * Always Return Global Endpoints * Added release notes * Fixed error with database initialization * Tests use free TCP/IP ports * Testing Refactor - this is a squash of 6 commits - original commits are vailable for cherry-picking here: https://github.com/ziadsawalha/keystone/commits/tests * Added HP-IDM documentation artifacts * whitespace * whitespace * make create_tenant work for keystone api * common ks client creation * Fixed version response (bug 891555 and bug 843052) * Implement Multiple Choices Response (bug 843051) * updating of docs * Fix LDAP schema (bug 904815) * working on a tenant_create test * standardize spacing * novaclient uses password instead of apikey * update to use the correct repo for python-novaclient * fix tenant auth tests * Updated namespace * Fixes the catalog return in d5_compat calls * Added: ./keystone-manage database goto * Added databased version check on startup w/ docs * Revised in-memory sql connection path for sqlalchemy * Clarify 'test not found' error message * Contract fix: change IDs from xsd:ID to xsd:string * Tenants - asserted all the things (bug 887844) * Support for unscoped admin tokens * LDAP: fix to keystone.ldif * Contract fix: IDs are not Ints, they are ID or string types * Contract fix: description optional * Update tracer excludes for Linux * Fixed bug 905422. Swift caching should work again. Also fixed a few other minor syntactical stuff * Update test_keystone_manage to use unittest2 * Python 2.6 subprocess.check_output doesn't exist * No more python path changes * Clarified language on migration instructions * Refactor: Workaround for python build_sphinx failure * Fixed some skipped tests * Format keystone-manage output better * Added instructions to git clone from github * Refactor: Computing api/model module paths dynamically * Introduces UID's & domain models (bp portable-identifiers) * Improved test coverage of d5 compat * Fixed: Tests returning successful (0) on failure * D5 Compatibility Support * Added original tenants blueprint to docs * Fixed broken import of version info (bug 902316) * Added missing import preventing keystone from starting (bug 901453) * Fix some issues with new version module * quantum_auth_token.py middleware fails on roles * Removed Server class from __init__.py * Fix auth_token middleware: make _verify_claims not static. Fixes bug #901049 * Pylint fixes to auth_token.py * Split version code into its own file * Change is_global == 1 to is_global == True * Bug 897496: Remove tenant id from Glance URLs * Refactor: move initialization code to class * Add missing json validation * Refactor: get rid of keystone/config.py * Fixes missed tests and subsequently introduced bugs * Rename .keystone-venv to .venv * Refactor: Rename auth controller to token controller * Added documentation * Added SSL and memcache sample config files * Updated auth_token middleware caching to support memcache * Deprecating RAX-KEY middleware * Added argparse to support python 2.3 - 2.6 * Make bin/keystone use port settings in the config file. Fixes bug #898935 * Bug#899116: use correct module when building docs * Minor RST changes * Revised extension documentation * Added documentation for SQL tables * Remove pysqlite deps. Fixes bug #898343 * Pretty-printed JSON samples * Added option to pretty-print JSON * Implements blueprint keystone-swift-acls * Updated docstring to match auth_token.py (bug 898211) * Bug #890801 Changes to support /extensions call. - Introduced a new extension reader to read static extension content. - Added additional rst files explaining extensions. - Removed functionality from additional middleware that used to support /extensions call.ie RAX-KEY-extension - Removed service extension test as it was no more relavent. - Added unit test that checks toggling of extensions. - Additional notes on the conf file * Added JSON validator; fixed samples (bug 898353) * Fixes a number of configuration/startup bugs * Fixed RST syntax (bug 898211) * Revised schema migration docs * Improved doc formatting consistency (bug 898211) * Fixed RST syntax in doc strings (bug 898211) * Added ssl docs to index; fixed rst syntax (bug 898211) * Bug-897724: Added method to list endpoints specific to a service and related tests * Eliminated debug output from sphinx_build (bug 898211) * Updated testing * Fixes bug lp:897819 * Check that endpointTemplate ID is valid in endpoint add cmd (#897749) * Added Endpoint and Endpoint Template documentation * Bug #854104 - Changes to allow admin url to be shown only for admin users. - Additional test asserts to verify * Fixed memcache tests * Update documentation and examples following API 1.1 removal * Fixes bug 843065 * Additional middleware test coverage * Enforce service ownership * Add keystone_tenant_user_admin option and fixes * Make owner the user named same as tenant/account * Restored developer default log dir * Add default for log directory and log filenames * Added wadls, pdfs, samples and functional test confs (bug 891093) * Additional documentation * ./keystone-manage endpointTemplates list missing arg (bug 891843) * Bug #890399 * Bug #891451: Changes to support update endpointTemplates call in the WADL * add an example for capability rbac * make readme use code style * add the policy code * describe and add a policy backend * policty stub * re-indent * Added timeout to bufferedhttp class and timeout setting for middleware - bug 891687 * Refactoring master to match stable/diablo fix for bug 891710 * Refactor auth_token.py to only call out to Keystone once * Added files missing from dist packaging (bug 891093) * pylintrc should not be hidden (bug 891093) * Simplified gitignore (in pursuit of bug 891093) * Fixes typo in setup document * Adding middleware tests * Remove executable bit on template * change array syntax * updates to make compatible with middleware * mergeish dolph's port change * fix tests * handle unscoped requests * adjust default port * Revised version status response (bug 890807) * Refactored headers produced by middleware (bug 835087) * move noop to identity controller * Ignoring db migrate mgmt module to workaround bug 889287 * 'text/json' should be 'application/json' (bug 843226) * Revised curl examples (bug 884789) * allow setting user_id on create * users require a name * pep8 * update test conf too * cli for adding users, tenants, extras * adjust paths and use composite apps * add tests for extras * add tenant crud * oops, forgot update in crud * add crud tests * add crud tests * add crud tests * add test for create user and get user * add test for create user and get user * re-indent identity.py * don't pep8 swp files * accept data as kwargs for crud * use the keystone app in the conf * reorg * re-indent service.py * Bug 888448: - Changes to allow validate token call return user name as per contract. - Additional test assertions to test the same. - Changes to middleware * more dyanmic client * get some initial identity api tests working * update service to middleware in confs * move around middleware * make a composite app * add crud methods to identity manager * Add a new swift auth middleware * Use TENANT_ID if it exists, but still support X_TENANT * cli beginnings * Bug 888170: Fixing references to incorrect schema * add admin port * add an etc dir * Bug #888210: Changes to fix calls to use the right path * bug 878431: Minor changes to auth_token middleware * add a default handler for / * Bug #886046 Add Quantum auth middleware to Keystone source code tree * add a stubby setup.py * use paste for the binary * add a trivial admin-only middleware * update keystone sample tests, skip one * Bug #887236: - Changes to allow extensions to be configured. - Introduced a new property that holds list of extensions that are to be enabled * add crud info to readme * get novaclient tests working * add novaclient, intermediate * add run_tests.sh and pep8 stuff * remove italics on Light * modify requirements * link diagrams * Track post-Diablo database evolution using migrations (BP: database-migrations) * Changed blatant hack (fixed spelling also) to 5 second timout as tests were not completing * Use TENANT_ID instead of TENANT for project_id * X.509 client authentication with Keystone. Implements blueprint 2-way-ssl * whitespace * added catalog tests * added tests for tokens * test the other methods too * add some tests and get others to pass * add some failing tests * add a default conf * minor whitespace cleanup * add some todo * fixed the output message error on granting user a role * Bug #884930 Support/Remove additional calls for for Tenant. - Supported call to get users for a tenant for a specific role. - Removed calls to get specific role for a user and to get all the roles for a specific tenant as they are not useful. - Fixed LDAP backend call to get users for a tenant. - Disabling Invalid pylint check * adding docs to test classes, updating run_tests.sh to match reality adding debug middleware factory adding docs on enabling debug middleware resolving pep8 issues * Fixes LP Bug#885434 - Documentation showing multiple tenants misleading * add example * rst blah blah * updated readme * authenticate and tenants working * working authenticate in keystoneclient * remove test_keystone_compat's catalog tests * add templated catalog backend * Use pure version number ("2012.1") in tarball name * Set run_tests.sh so pep8 runs in the virtualenv * bug 885364 * bug:884518 Changes to support passwordcredentials calls as per API contract. Minor LDAP code change to support tests * Fixed spelling of 'Resources' (Resoruces) * pep8 cleanup * everything but the catalog * Remove execute bit on keystone.conf * Fixes LP882760.Changes to return TenantId properly as part of roles.Additional tests to support the same * Moving contributor docs into rst (bug #843056) * fixing search sequence to not include directory structure from os.walk() * bug lp:882371 Standardize Json pagination structures * get a checkout of keystoneclient * bug lp:882233 Code changes to support API calls to fetch services/roles by name * Removed contributor doc build info from project README (bug #843056) * Revised documentation build process (bug #843056) * updates to keystone documentation - install & conf bug 843056 blueprint keystone-documentation * Specific LDAP version causing hiccups installing on latest ubuntu & fedora * Adding the concept of creating a Keystone HTTP client in Python which can be used in Keystone and imported from Keystone to allow for easier Keystone integration * Add .gitreview config file for gerrit * updating keystone developer documentation updating docstrings to remove errors in automodule generation updating setup.py to generate source documentation blueprint keystone-documentation bug 843056 * Changes to support getuser by name and gettenant by name calls * Changes to support get endpoints for token call * Additional changes to support endpointtemplates operations.Disabling pylint msgs that dont fit * Github markdown doens't seem to like irc:// links * Removed 'under construction' docs provided elsewhere * Updated self-documentation to point to docs.openstack.org * Revised documentation * Changes to endpoint operations as per OSKSCATALOG contract. Adding couple of pylint fixes * Refactored version attributes * Changes to support endpointTemplate operations as per new API.Fixed issues with command line manage stuff * Updated Secret Q&A to extend CredentialType * Changes to support API calls as per OS-KSCATALOG extension * Improved CLI error feedback (bug 877504) * authenticate working, too * base tests on keystone-diablo/stable * get tenants passing, yay * flow working, added debugging * add context to calls * move diagram into docs dir * refactor keystone compat and add catalog service * added sequence diagrams for keystone compat * Resubmitting change. Fixing issue #843226. Changes to throw appropriate faults during token validation * bug lp:865448 change abspath to dirname in controllers/version.py to correct path problems * Moving non core users and tenants calls to appropriate extensions * Fix issues in the ec2 middleware * Adding calls to get roles for user as per new format.Cleaning references to old code * Fixes LP844959, typo in Authors file * Changes to support roles and services calls via extensions. Change-Id: I1316633b30c2be07353dacdffb321791a4e2e231 * Simplified README * First commit for Secret Question and Answer Extension: RAX-KSQA * Fixing issue 854425.ie chaning token table name to tokens. Fixing issue 863667.Changes to support updation of user/tenant name as well using api calls. Fixing LDAP backend to have id independent of name.Fixing getuser call to also return name * Fixing bug 859937. Removing incorrect atom feed references from roles.xsd * Minor corrections to the middleware and wadl * Changes to show name also for the user list * Changes to show admin URL also as a part of json in endpoints listing * getting closer, need to match api now * tests running through, still failing * add a test client * added a test, need to get it working now * Use the tenant name for X_TENANT * Fix possible_topdir computing * Change roleId to role.id for swift middleware * adding in doc and setup to cover existing scripts adding doc around credentials command usage (for EC2) 2011.3 ------ * Updating legacy auth translation to 2.0 (bug #863661 * Shouldn't look in /etc/init/ for config files * Changing default admin port from 5001 to 35357, per IANA/IETF (bug #843054) * Organizing and documenting pypi requirements * sample data updates to remove -service from image and identity * Refactor and unit test json auth parsing * Error message expecting 'e' in local scope * Do not return identical error messages twice * Update auth examples in README * README.md changes to point to openstack repo * updating docs for Mac source install, no docs for mac package install relevant * POST /tokens: Added tenant id & name to scoped tokens in XML (#862752) * Updated guides.Have recompiled to use the latest examples * Fix bug 861546 * Fix swift middleware with regard to latest changes * Changes to support getTenants to behave differntly for admin users when invoked as a service api or admin api * Changes to stored hashed password in backends. Using passlib a password hashing library. Using sha512. Setting hashing to be the default behavior * Changes to WADLs to refer actual types * Revised docstring * Added /etc/init/keystone.conf to list of known configuration paths * Revising tenant IDs & Names in samples (#854228) * Authenticating against non-existent tenant (fixed #859927) * Adds list of dependencies to dev install * Fixed Anne's email address & list position (alphabetical) * Added support for scoping by tenantName * Changes to return groups as a part of RAXKSGRP extension.Also fixed incorrect schema version references in wadls and examples * Changes to support authenticate call to accept token as per agreed format * Minor changes to wadl * Making type mandatory as per sandy's request and minor fixes to wadl examples. Adding Ann as an author * Changes to structures to support authenticate using token. Minor wadl fixes. Adding Anne as an author * Removing token element from token.xsd * Update to token.xsd to allow element token as a root element in relation tu bug: https://bugs.launchpad.net/keystone/+bug/855216 - apiKeyCredentials Samples casing apiKey update * Changes to support endpoint template addition/listing by service names. Changes to list service details as well * Modified apiKeyCredentials to extend single entity and use restriction * Reorder params in User() constructor * Fix for bug 856857 - add user.name to User() constructor to re-align param * Fix for bug 856846 - cast ints to string in users_get_by_tenant_get_page so that they can be joined * POST /tokens: A chronicle of missing features * Fixes issues with ldap tests * Get Service Catalog from token * Fixes auth_token middleware to allow admin users in nova * Initial set of changes to move role operations to extensions * Updating guide wrt wadl changes * Minor Changes to extension WADL * Changes to support auth catalog as per new format * Changes to docs * Adding tenantid to user roles and endpoints * Fixes bug 855823 * Add code removed in https://code.launchpad.net/~vishvananda/nova/remove-keystone-middleware/+merge/76297 to keystone * Added support for HEAD /tokens/{token_id} Changed POST /tokens response container from 'auth' to 'access' * Making identity-admin.wadl well-formed * Converting to new doc format for included code samples * Changing authenticate request content xml as well as json * GET /tokens/{token_id}: Exposing both role ID's and Name's * Renaming 'roleRef' container to 'role' * Renaming 'roleRefs' container to 'roles' * Renaming GET /tokens/{token_id} response container to 'access' * Revised samples * Fixed path issues with keystone-import * Update validate_service_or_keystone_admin_token so that it doesn't cause exceptions if the admin or service admin haven't been configured * Changing/introducing actual extension json/xml snippets. Adding updated documents * Backend-managed role & service ID's (bug #834683) * Initial Changes to move service operations to extensions * Docs,wadls,samples,initial code to support RAX-KSKEY and OS-KSEC2 extensions. Removed tenant id from being part of endpoints * Glance Auth Token Middleware fix * Sorted AUTHORS list * adding imports from Nova for roles, tenants, users and credentials * Update keystone-manage commands to convert tenant name to id. Fixes #lp849007 * 1.Changed all Json paginated collection structure. 2.Introduced a type for credential type (path param) and change wadls and xsds. 3.Added List Users call. 4.Changed Endpoint creation example * Don't import keystone.test unless we are in testing. Fixes #lp848267 * Add toggle to run tests in-process, w/ realtime progress feedback * Add ability to run fakeldap in memory * Added backend-managed primary key to User and Tenant model * Introducing doc to support OS-KSCATALOG extensions.Adding new calls to OS-KSADM extension document * Adding initial document for OS-KSADM-admin extension.Related changes on wadl,json,xsd etc * Fixing sample content * Adding new doc.Changes to sample xmls and jsons * Validation content and relavant changes * Minor fixes on xsds and sample xmls * Fixing existing wadl.Completing wadl for extension OS-KSADM * Fix invocations of TemplateError. This exception takes precisely three parameters, so I've added a fake location (0, 0) to keep it happy * Adding wadl for OS-KSCATALOG extension.Fixing existing xsds.Fixing service wadls. Merging changes. Change-Id: Id29dc19cbc89f47e21329e531fc33bd66c14cf61 * Update Nova and Glance paste config examples * Various documentation-related changes * Consolidating xsds. Splitting contrib to admin and service * Adding guides for groups extension * Fix host/port split code in authenticate_ec2. Resolves an AttributeError: 'Ec2Credentials' object has no attribute 'partition' exception that can occur for EC2 auth validations * Adding guide for RAX-KSKEY-service extension. Adding guide for OS-KSEC2-service extension * Fix NameError exceptions in add_credentials. Adds test case on creating credentials * Redefining credential types. Defining additional extensions and renaming extensions. Removed wadls that are not needed * Fix for duplicate tag on credentials.xsd * Move tools/tracer into the keystone code. Fixes ImportError's when running keystone as a .deb package * Fixed error where endpoints returned for tenant instead of token * Updated the AUTHORS file to test the new rpc script and workflow * Update rfc.sh to use 'true' * Made it possible to integrate with external LDAP * Dev guide rebuild and minor fixes * Updates to samples, XSDs, and WADLs * Added AUTHORS, .mailmap and generate_authors.sh * Changes to support endpoint template updates * Fixes bug 831574. Adds missing sys import * Updated schema to reflect id and name changes to Users and Tenants * Updated guides and samples * Additional contract changes * Sample changes * Atom links on Token * Cleanup service it endpoint catalog * Removed redundant function from base user api * Updated samples * Fixed reference to unassigned variable * Reworked XSDs and WADL to support auth and access elements * Remove more group stuff * Removed OSX files that shouldn't be in git * Documentation cleanups * Banished .DS_Store * Add rfc.sh for git review * Wrong common namespace * XSD & sample updates * Added more missing files to MANIFEST.in * hanges to allow test to work on python 2.6.* * Cleaned up come issues with python2.6 * Refactored manage.py to be both testable and useful for testing * Sample changes to support v2.0 api * Sample changes to support v2.0 api * Admin WADL Revisions * Add the files in keystone/test/etc * Add run_tests.* to the MANIFEST.in * Keystone manage.py cleanup * Tests running on in-memory sqlite db * Additional changes to fix minor service support stuff and increase test coverage. Also making validate token call available using service admin tokens * Made all sample data loading in one script * Minor fix to run_tests * Contract changes * Admin WADL updates * Port of glance-control to keystone. This will make writing certain keystone integration functional tests a little easier to do * Updates to XML and JSON changes for validateToken * Added pylint message count as run_tests.sh -l * Added reponse handling for xsd static file rendering III Extra extension tests (for RS-KEY) * Creating an artificial whitespace merge conflict * Moved run_test logic into abstract class * Git-ignore python coverage data * Added reponse handling for xsd static file rendering * Additional tests and minor changes to support services CRUD * Added reponse handling for xsd static file rendering * Schema updates. Split WADLs and extensions and got xsds to compile * Ziads changes and fixes for them * Added check_password to abstract backend user API * Doc changes, including service catalog xsd * Fixed service-bound roles implementation in LDAP backend * Removed ldap names import from fakeldap module * fix ec2 and add keystone-manage command for creating credentials * Legacy auth fix and doc, wadl, and xsd updates * Replacing tokens with the dummy tokens from sampledata.sh * Add option for running coverage with unit2 * Adding curl documentation and additional installation doc. Also updated man documentation for keystone-manage * Changes to improve performance * Removed the need to set PYTHONPATH before tests * Back to zero PEP8 violations * Schema and WADL updates * Adding documentation to WADL * Correct 401, 305, and www-authenticate responses * Correct 401, 305, and www-authenticate responses * Correct 401, 305, and www-authenticate responses * Added xsd content, update static controller, and static tests * Updated wadl * Fix LDAP requires to compatible version * Moved password check logic to backend * Changes to delete dependencies when services,endpoint_templates,roles are being deleted. PEP8 and Pylint fixes.Also do ldap related changes * Add LDAP schema * Add wrapper for real LDAP connection with logging and type converting * Fix console and debug logging * Redux: Add proper simple_bind_s to fakeldap * Adds support for authenticating via ec2 signatures * Changes to allow additional calls to support endpoint template CRUD and additional checks on existing method * Committer: Joe Savak * Refactoring business logic behind GET /tenants to make it less convoluted * Moved run_tests.py to match other projects * Revert "Add proper simple_bind_s to fakeldap, removed all imports from ldap." * Add proper simple_bind_s to fakeldap, removed all imports from ldap * Gets Keystone a bit more inline with the way that other OpenStack projects run tests. Basically, adds the standard run_tests.sh script, modifies the run_tests.py script to do the following: * Changes to support CRUD on services/roles * Issue #115: Added support for testing multiple keystone configurations (sql-only, memcache, ldap) * Added automatic test discovery to unit tests and removed all dead tests * PEP8 fixes... all of them * Small licensing change to test Gerrit * Small change to test Gerrit * Fix brain-o--we may not need project_ref, but we do need to create the project! * updated README with more accurate swift info * Determine is_admin based on 'Admin' role; remove dead project_ref code; pass auth_token into request context; pass user_id/project_id into request context instead of their refs * Added support for versioned openstack MIME types * #16 Changes to remove unused group clls * Add unittest2 to pip requires for testing * #66 Change in variable cases * #66 Change in variable cases * Changes to make cache time configurable * Changes to store tokens using memcache #66 * Changes suggested by Ziad.Adding validateToken operation * Flow diagram to support keystone service registration * Restored identity.wadl w/ system test * pylint fixes for role api * Removing attribute duplicated from superclass; causes an issue in py 2.7 * pylint fixes for tenant-group unit tests * pylint fixes for server unit tests * Making the API version configurable per API request * PEP8 fixes for system tests * Issue #13: Added support for Accept-appropriate 404 responses w/ tests for json & xml * Simple change to test gerrit * Document how to allow anonymous access * Sigh. Proofreading.. * Update README with instructions to fix segfault * These changes make no sense--I didn't do them, and I'm in sync! * Add middleware for glance integration * #3 Preventing creation of users with empty user id and pwds * Fixing naming conflict with builtin function next() * This makes the use of set_enabled more clear * Fixes failing test introduced after disabled check remove * Changes to allow password updates even when the user is disabled.Also fixed failing tests * Disabled users should now be returned by GET /users/{user_id} * Updating a disabled user (via xml) should now succeed * Updating a disabled user should now succeed * Noted potential issue, but I'm not sure if this is dead code or not anyway? * Assigned Base API classes so downstream code knows what to expect * Adding missing class variable declaration * Cleaning up unit tests * Removes disabled checks from get_user and update_user * Fixing module-level variable naming issues * Improving variable naming consistency * Avoiding overloading of built-in: type() * Fixing indentation * Specified python-ldap version, which appears to avoid the packaging issues we've experienced * Added missing import * More LDAP tweaks * LDAP backend updates * More test fixes * Fixed deprecation warning * Updated test to allow for additional role * Restored UnauthorizedFaults to token validation requests * Fix for issue #85 * - System test framework can now assert specific response codes automatically - Revised system test for issue #85 based on clarification from Ziad - Added system test to attempt admin action using a service token * Adds the member role to sampledata, gives it to joeuser * PEP8 fixes * Formatting * Merged duplicate code * Add first implementation of LDAP backend * Added (failing) system test for issue #13 * Minor cleanup * Made all API methods raise NotImplementedError if they are not implemented in backend * Made delete_all_endpoint calm if there is nothing to do * Fixed bug causing request body setting to fail * Add check to sqlalchemy backed to prevent loud crush * Tweaked import_module to clearly import module if it can * Removed hardcoded references to sql backends * Add exception throwing and logging to keystone-manage * Merging keystone.auth_protocols package into keystone.middleware * - Added 'automatic' admin authentication to KeystoneTestCase using bootstrapped user - Added system tests for admin & service authentication - Abstracted '/v2.0' path prefix away from system tests - Added simple uuid function to generate data for system tests (random number gen w/ seeds might work better?) - Refactored issue #85 tests with setUp & tearDown methods * Clarifying test case * Fixed minor pylint issues * Removed tenant id from admin user * Move dev guide to OpenStack * Commented out failing request, until it's review * Wrote test case for github issue #85 * Formatting change * Was this a typo or an incredibly lame joke? * Added missing imports and fixed a few pylint issues * Improved dict formatting * Improved readability a bit * Abstracted underlying HTTP behavior away from RestfulTestCase Added 'automatic' JSON body encoding (TODO: automatic XML encoding) Improved user-feedback on automatic response status assertion * Added run_tests.py to keystone.test.system, which uses bootstrap db script * Added bootstrap configuration script (with admin user assigned an Admin role) * Added 'automatic' token auth for each API * Refactored port configuration strategy to allow a single test case to address both the admin and service API's * Added automatic json/xml parsing to system test framework * Added system test discovery to run_tests.py * Added system tests for content type handling and url rewriting * Updated tests to reflect last bug fix * Extracted sample test from framework and moved system test framework into __init__ * Converted system test framework to use httplib * Initial system test approach, using urllib2 * Fixed bug: traceback thrown when the path '/' is requested * Updated *unused* tests to reflect refactored API's * Removed some useless/dead code * Cleaned up authentication tests * Improved readability slightly * Moved db imports to config module Removed useless try/except blocks * Organized imports * Simplified a few util functions * Fixed line length * Renamed service API configuration options * Renamed ServiceApi router module * Renamed ServiceApi router * Cleaned up keystone.logic * Removed unused logger * Refactored routers and controllers into their own modules (issue #44) * Fixed doc string * Improved PEP8 compliance * Fixed spelling * Removed unused import * Slightly simplified base wsgi router * Added note about run_tests.py to readme * Organized imports * Improved readme consistency * pep8 * Pylint an pep8 fixes * Fixing bug reported using with swift * Fixed default content type behavior (was defaulting to XML) * Removed redundant action mappings (for version controller) * Renamed exthandler to urlrewritefilter to better illustrate it's purpose * Minor comment change * Refactored URL extensions handling (for .json/.xml) Added universal support for optional trailing slashes * Return users in a tenant as part of a many-to-many relationship * Added import, autoformatting * Removed unused imports * Moved exthandler to keystone.middleware * ** keystone.conf refactoring ** * Fixed 'is_xml_response' function, which had no clear intention * Removed unused function * Rewrote .json/.xml extension handler with additional unit test * Added links to readme * Added python-ldap to pip-requires * Initialized LDAP backend * Various fixes for test running * Commented out suspicious unit tests..... * Added test automation script * Cleaned up file * Added missing test files to test collection * Made unit tests executable from the cmd line * Added test_auth to list of unit tests * Update auth test to account for generic service names * Changes to make Admin for keystone configurable.#27 * Remove old initializers * Changes to introduce BaseAPI to support multiple back ends * Changes to support dynamic loading of models * Adding list of todos * Initial changes to support multiple backends * Fixed identity.wadl response - issue #71# * Recompiled devguide with endpoints and templates * Removed unnecessary symlink * Changes to support endpoints and endpointemplates (renaming BaseUrls and BaseURLRefs) * Make swift middleware live where it should * Remove swift-y bits from generic token auth * Changes on Sample data * Code changes to support global endpointTemplates * Swift-specific middleware * Issue 31: Switching default ports to 5000/5001 (public/admin) * Fixed readme instructions for Nova - Issue #55 * Fixed requires for development and in readme * Bringing back the changes to support endpointTemplates and endpoints * Readme fix * Edited keystone/auth_protocols/nova_auth_token.py via GitHub * Issue 32: Updated readme to reflect fix for issue 32 (removed 'cd bin' prefixes before several commands) * Issue 32: bin/sampledata.sh cannot be executed outside of bin/ * Issue 32: ./bin/keystone cannot be executed outside of bin/ * Issue 31: Reverted ports to 8080/8081 while the issue is under discussion * Adding endpoint related files * Updated readme to reflect docs/ -> doc/ change Added tools/pip-requires-dev for depelopment dependencies * Basic authorization for swift * Republished developer guide for Jun 21, 2011 * Updated token validation sample xml (dev guide) * Updated dev guide publish date * Added developer guide build folder to git ignore list * Auto-formatted and syntacically validated every JSON example in the doc guide * working with dashboard * add get_tenants * rudimentary login working * most bits working * initial * Reverting change thats not needed * Fixing some of the failing tests * Merging changes from trunk * demo of membership using keystone in sampledata * Name changes BaseURLRefs to EndPoints and BaseURLs to EndpointTemplates * Fixed formatting, imports * Issue 31: Updated docs and examples * Committing unit test configuration for issue 31 * Issue 31: Changed default ports to 80/8080 * Issue #8: Renamed primary key of Token to 'id' * Name changes BaseURLRefs to EndPoints and BaseURLs to EndpointTemplates * Changes to hash password * Restored tools.tracer to bin/ scripts; included fix for empty frames * Merging changes * Removed unused import * Removed redundant sentence in dev guide * Removed unused imports in bin/ * Fix for keystone issue 41: https://github.com/rackspace/keystone/issues/41 * Merging changes from rackspace * Fixed spelling error * Changes to include support for paginations * Fixing existing methods on wadl * Fixed broken unit test code * Refactored api function names to avoid redundancy with new module names * Changes to wadl to support user operations * Refactored DB API into modules by model * Pep8 changes * Changes to allow user creation without a tenant * for got to change a 1.1 to 1.0 * dash needs both 1.0 and 1.1 compatability - need to fix that! * nova needs 1.0 api currently * Some field validations * Merged docs * make sampledata executable again * Admin for nova doesn't take a tenant * add keystone to its own service catalog * Fixed error on UrlExtensionFilterTest * Fixed imports; improved PEP8 formatting compliance * Fixed imports in keystone.common * Removed unused imports and denoted unused variables * Fixed imports in auth_protocols * Removed duplicated function * Added coverage to pip development requirements * Fixed relative & unused imports * Adding py init to functional tests * Created pip requirements file for development env (added sphinx python doc generation to start) * Added pydev files to gitignore * Added py init files to directories already being referenced as modules * Users must have tenants or nova breaks * Doc updates and dev requires * Resolved conflicts * To PUT or to POST * Fixed v1.0 auth test to account for cdn baseURL order * Support for GET /v2.0/users and add cdn back to sampledata for v1.0 support * Update the baseURL data pushed into glance * Fix symlinks after docs -> doc rename * Adding call to modify tenant.Adding more tests and fixing minor issue * Added pip requirements file for testing environments * Grammar corrections * Adds Sphinx build ability and RST documentation * Removing unused references to UserTenantAssociation * Introduced a method to get all users @Users resource.Also moved the method to get user groups out of tenant scope * Changed BaseURLs to OpenStack names * Test fixes * Seperating user calls from tenants * Improved README formatting/consistency * Updated paths to unit/function tests in README * Updated docs: sampledata.sh can't be executed outside of bin/ * Added Routes and httplib2 to production dependencies * Correcting typo * Setup.py fix * Readd test folder * Forgot to add doc file * Moved tests to keystone folder and removed old management tools - issue #26 * Updated SWIFT endpoint default * Update to dev guide explaining admin call auth requirements * Update sample data and keystone-manage for local install of OpenStack * Put updated Swift Quickstart into README.md * API v2.0 Proposal * Doc updates.Minor keyston-manage changes * Doc updates * Doc updates * set nova admin role if keystone user has "Admin" role * keystone repo is now at github.com/rackspace/keystone * Add success test for GET /v2.0/tokens/ in json and xml * Add Admin API tests for v2 authentication * Add test verifying a missing tenantId key in the password creds works properly in JSON * Rename file.Ziad suggestion * Name changes suggested by Ziad * Minor fixes * Code cleanup * PEP8 changes * Removing redundant files * Changing to legacy auth to standard wsgi middleware.Name change of some of the files * Changing to legacy auth to standard wsgi middleware * Introducing new frontend component to handle rackspace legacy calls * Introducing new frontend component to handle rackspace legacy calls * keystone repo is now at github.com/rackspace/keystone * Add success test for GET /v2.0/tokens/ in json and xml * Add Admin API tests for v2 authentication * Add test verifying a missing tenantId key in the password creds works properly in JSON * Removing debug print * Changes to return service urls for Auth1.0 style calls * Changes to return service urls for Auth1.0 style calls * Updating tests and sample data * Merging changes from rackspace * Changes to support service catalog * pep8 * Added URLs to sampledata * Support for listing BaseURL refs in keystone-manage * Support transforming service catalog * Removing remerged comments * Adding roles as comma seperated values on a single header * Changes to support getTenants call for user with admin privelage and regular user * Add more test cases for v2 authentication for bad requests and unauthorized results * Add test case for verifying GET /v2.0/tokens returns 404 Not Found * It's possible to authenticate through the Admin API * Changes on auth basic middleware component to return roles.Also changes on the application to return roles not tied to a tenant * Update the sample to reflect some minor enhancements to the base framework * Add test for validate_token * Save expiration data for later comparison * Don't need to fiddle around with user tokens here, just admin tokens * Get and revoke both admin and user tokens.. * Merging changes * Bah, somehow my sample data failed to include Admin as admin's role * Merging changes * Merging changes * Merging changes * Meging changes * Changes to also return role references as a part of user when get token call is made for a specific tenant * Use un-spaced exception names.. * Try to use an admin credential to revoke the token * Split the Keystone service from the Admin service so we can test both * The API is a moving target; update the test * Support for listing roles in keystone-manage * Adds unit testing base class that takes care of much of the tedium around setting up test fixtures. This first commit just demoes the new test case functionality with a new test case /test/unit/test_authn_v2.py * pep8 * Fixed issue #6 * Support POST /tokens only - issue #5 * Added quick start guide to integrating Swift and Keystone; fixed setup.py tokenauth filter installation * Added role and user data to sampledata.sh * Additional unit tests for base url refs.Minor code refactorings * Changes to support baseurlrefs operations * MD cleanup * md futzing * More readme cleanup * Merged DTest tests and moved ini file to examples/paste * moved paste example to examples * Readme updates * Just making sure leading whitespace is stripped if automated * to->too * Updated dev guide * Add a sample to document how to create tests * Add a test for authenticate/revoke_token * Ensure that --username, --password, and --keystone are given * Build base classes for tests * Documentation fixes to versions * Build the skeleton necessary to run tests * Add x_auth_token header to most methods * Make sure we don't lose the body completely if we can't json.load() it * Add debugging messages * Add a property to get the RESTClient instance * Fix up get()/put()/post()/delete() calls to make_req() * Deal with the case that no headers are provided * Deal more intelligently with empty strings * Listing technologies to integrate * Um, queries are supposed to be optional, all others required * Properly join relative paths * Apparently "/token" is actually spelled "/tokens" * Accidentally left out the reqwrapper argument * Sketch in a basis for the Keystone API 2.0 * Make argument order a little more natural * Fixing unit tests.Introduced support for global roles * Don't let self._path be the empty string * self._scheme isn't set yet * Don't add a field if there isn't one.. * Create a simple means of building a REST-based API * Fixing unit tests for user and groups * Docs * Link fix * API Spec updates * More /token -> /tokens fixes * /tokens instead of /token * Prep for move to git@github.com:rackspace/keystone.git * Made URL relative * pep-8 and minor mapping fix * Dev guide update - BaseURLs and Roles * Update docs on how to use nova.sh to deploy openstack on cloud servers * Changes to support calls to getBaseUrls * Changes to support /tokens on docbook and minor roleref changes * Changes to support roleref calls * Updated to use X_USER as decided in Issue 49 * Updated with feedback from https://github.com/khussein/keystone/issues/49#issuecomment-1237312 * Fix for issue 49 - parse X_AUTHORIZATION header for user_id * Fixed issue where user tenant not returned in GET /token - related to issue #49 * user should be what keystone returns * Fixed issue #54 * Updated to use X_USER as decided in Issue 49 * Updated with feedback from https://github.com/khussein/keystone/issues/49#issuecomment-1237312 * Fix for issue 49 - parse X_AUTHORIZATION header for user_id * Minor changes to the document * Changes to unique relationship definition * Adding more tests for roleref operations * Fixed issue where user tenant not returned in GET /token - related to issue #49 * Changes to support /tokens on docbook and minor roleref changes * Changes to support roleref calls * user should be what keystone returns * midnight typo * Added examples readme * Fixed issue #54 * Link to latest dev guide in readme * Instructions to run with Nova * Documentation update and new API spec * Updates to README * Updates to README * Updates to README * Updates to README * Updates to README * Updates to README * Fix up broken setup.py scripts list * -Removed .project file from project and added it to .gitignore -Moved pylintrc -> .pylintrc, personal preference that this file should be available, but not seen -Moved echo to examples directory, seemed a bit odd to be in the top level -Moved management directory to tools, seemed a bit odd to be in the top level -Moved pip-requires to tools/, and updated the reference to it in README.md * Fix the identity.wadl symlink * keystone src directory needs symlinked * remove copy&paste ware from nova_auth_token and use auth_token middleware * Flow diagrams * simple flow diagrams * Multi-tenant token fixes * Fixed invalid tenant authentication * Fix error in tenant_is_empty (model has changed) * Fixed debug/verbose flag processing * update readme * keep nova_auth_token in keystone * Changes to support /Roles calls.Removing create call from being exposed as of now * Changes to support /Roles calls.Description included * Changes to support /Roles calls * Readme merge * Readme updaes for load testing * hack nova_auth_token to work * removing unused library * Changes to support roles and baseurls on wadl * Changes to support roles and baseurls on wadl * Changes to support roles and baseURLs * missed some nova reqs * information on using nova_auth_token * lazy provisioning for nova * readme fixes * Merged in anotherjesse's changes * New model working with echo_client.py * Missed a file * Added tracing and modified model * echo_client should be executable * move nova's path injection to management scripts * server.py/version.py shouldn't be executable while cli tools should * spacing for readme * Add keystone-manage to support bootstrapping Keystone with add user command * Setup.py update * Updated logging and parameterization for bin scripts * Minor readme fixes * Simplified running Keystone and Updated readme * v1 compatibility and Service/Admin API split * DocBook Changes * Merging HCL changes - pull 40 * Changes to support baseurls and roles on the document.Adding sample files * Changes to support baseurls and roles on the document * Adding xsds to support roles and baseurls * More version fixes * Initial commit * Make config compatible with legacy * Move to v2.0 * Changes to move the db settings to conf file * removing bottle * Adding Accept header to is_xml_response logic * Removing bottle dependencies * Mae Pylintrc, reordered imports made pep8 of the files * Foundation for some server and auth unit tests * Added as per HACKING Files * pylint fixes * fixes * fixed test cases * Merged api,service,server,test_common * Added test cases for add user to a tenanat * multi token test cases and bug fixes * Moved all Server functions to utils.py * Fixed failing test - bug introduced in cleanup * Added pylint and cleanup from last commit * Merged pull 37. Removes bottle, adds configuration, and adds daemonization * fixed pylint * fixed bugs * fixes * fixes * removed backslashes * Added functionality add user to a tenant * fixes * Pep8 test_users.py * checking SSLv3 problems * checking SSLv3 problems * checking SSLv3 problems * checking git push problems * Optimised test_users.py * Modified the README and README.md * fixed bug raised when included exthandler * Removed unwanted file * removed unused run method * Added PEP8 to test cases * Removed importing objects from keystone * pylintrc optimization * optimization of test cases and handling multi token * fixes * Nochanges * Modified the README for keystone-control issue * Modified the README * Added PEP8 for remaining test cases * PEP8 for test cases by praveena * renamed test_identity.py to test_keystone * added pidfile and removed print statement from test_common * fixes * removed print statement * Added keystone.log to ignore list * Modified server.py tenant group URL to fix failing test cases * Added *.log to gitignore * neglect changes * Added new script to run all tests * Modified and tests. Tests groups throwing some minor errors still * Modified and commented the code * Split the test cases into individual files Fixed Bugs of api * Made PEP8 of server * Too much of duplication and incomplete conflict resolution in test_identity.py * Sisirhs changes * Sai and Praveena's Changes * Added missing tests, mad e enable and disable password work * merged conflicts * test cases modfications and bug fixes * Renamed to server.py and added top dir in config * Added the keystone top dir in configuration * Modified the README * latest updates * latest updates * new merge with installation fixes * A brief README for the auth-server * Added keystone-control * chasing tenant group bug * Added tests for the URL extension middleware * modified keystone-control and reshuffling of file names * Adding unit test for the URL extension handler * Modified test cases * Yes, I modified, but I wont commit * merged Sai changes * Installation of keystone done * corrects charset=utf=8 * Working on echo server * one more push * move the template code from bottle into a separate file: * modified auth_server.py * Added echod and renamed echo.py to server.py * Minor cleanup + pep8 * merging changes from sai branch * saving changes to auth_server.py * get version implementation s Please enter the commit message for your changes. Lines starting * get_version_info is still not working * in the middle of get_version_info * Modified test_identity * removed .auth.serve.py.swp * Added some more functions through Routes and mapper * Update for Abdul * My Changes part 2 * modified Resposne to resp=Response() * My Changes * minor tweak * Some more cleaning up of git merges * Cleaning up of git merges * Added glance type of eventlet, because of its plug and play which meets the need of running everything independently if needed * pep8 and fixes * Readme updates * Removed keystone.db - should be generated by ORM * Removed extra files from last commit * Removed Global groups tests, which still needs to be tested. Updated README on how to run unit test * Deleted keystone.db * Merged pagination * Git problems - lingering commit * Renamed identity.py to server.py and added bin directory * Adding router to requires. Updating standards in HACKING. Removing schema (generated from ORM) * Added pagination functionality and tenant_group functionality with unit tests * Removing unused imports * Removing unused function * unwanted file * added the code that would go to hussein repo * Added tenant groups in identity, created test cases for tenant groups * Added latest changes to sirish branch with pagination for get tenants * Annotate TODOs * argument handling in echo.py * getting pep8-y with it * Merged conflicts * Basic auth and refactor * more pep8 * testing merging * get _tenants pagination updates * Merging keystone code * Basic Auth support * 17: query extension works * Issue 17: Adding tests * removed \r chararcter from unit directory * removed windows newline characters from management folder * removed unwanted files * Adding First kestone repo * Add Description File * sai added by sai * Foo2 * Foo * Initial * Minor changes + call using WSGI instead of bottle * Restored remoteauth * Reverted accidental(?) WADL deletion >:-( * Renamed protocol modules to auth_[type] Renamed PAPIAuth to RemoteAuth - better documented it and added redirect to auth_token (to stop using this) Cleaned up ini files and ini file handling (removed hard-coded defaults) * simple json cleanups for tests * pep8-ize * Added protocol stubs (openid and basic auth) * Renamed delegated to 'delay_auth_decision' Remove PAPIAuth Rename folder to Auth_protocols (that is where we add protocol components)Get_request -> get_content Make protocol module more generic (prepare for superclassing and multiple protocol support Refactor Auth_protocol_token If no token, bail out quick (clearer) same with if app Break out headers: - here is what is coming in - here is what we add - explain the X in headers: extended header * Updated Readme, and added TODO * Added XML/Json tests to the identity and updated the README * Fixed issue with standalone install * Updated readme * Fixed remote proxy issue * draft remote proxy: needs fixing * Updated readme and echo_client * Adding remote echo ini file * Fixes to middleware, ini parameters, and support for running echo remotely * replaced localhost with config * modifide middleware; echo_client works * Fixing and documenting middleware * Merged pull request #30 from cloudbuilders/master * Updated management scripts to use SQLAlchemy * Fixed SQLAlchemy db location to keystone directory * Added unit tests and updated the README.md on how to run it * made echo test work * get_request is actually init model from request contents * missed simplejson assumption * finish removing simplejson * pythonizing * update fault to be pythonic * remove unpythonic properties from atom and tenant * error decorator and logging unhandled errors * missed auth_data * fix typos * more pythonic * we don't need properties yet * use string formating * use relative import in init * fixed paste configs to run without eggs * Fixed mistake in port for echo service * Added echo_client.py * keystone.db should be in keystone dir * pep8 / whitespace * gitignore pyc files * split out running and installing sections in readme * allow apps to be run without setup.py * add command for test database to readme * echo has a separate setup.py * httplib2 isn't used * spacing * add httplib2 to deps and sort them * Added pip-requires and updated readme to include missing deps * explict installs for python libraries * update readme formating * update readme to be markdown * Updated readme * Doc fixes * Friendly error message if a user is not associated with a tenant * Ensure schema complience assertion is on in all tests * Whoops, details element is optional in faults * Remove identity (1) stuff and renamed identity2 to identity * Added wadl and xsd contract links * Adjust reletive links in schema * Comment seperators * Init version links * Initial version support * Initial extensions support * Initial update tenant * Make sure we don't delete non-empty tenants * Initial delete tenant * Initial getTenant * Minor updates to tests * Initial implementation of get tenants * added unit tests in test/unit/test_keystone.py * Initial create tenant * Minor bug when serializing tenant to JSON * Schema update * Whoops forgot 409 in JSON as well! * Whoops missed 409 on create tenant * setup.py fix * Minor fixes * pep-8 cleanup of model * More pep-8 cleanup * Minor fixes * Some pep-8 cleanup * Initial revoke token * Initial support for authenticate * Whoops, bad user data * Initial working validate token * Whoops need to convert datetimes to iso format * Test updates * tokenId should not be a string! * Cleaned up validate token call * Full check admin token with soap ui tests * Some SQL testing scripts * Initial check admin token from db * made identity.py pep8 compliant * Better error handling * Initial full response to authenticate token, still having issues with errors * Stubb for token calls * Initial prototype of default token based auth protocol * Initial deserialization of tenant * Initial deserialization of password credentials * SQL Alchemy additions: Token * SQL Alchemy additions * Whoops pep8 * Output serialization of faults * XML and JSON rendering on tenant/s * Translations of auth to XML and JSON * Sample service.py with sqlalchemy * Fixed relative path issue * sqlalchemy draft * Initial service.py * Cleaned up setup.py * Added collections * Initial atom link type * Initial fault type * Initial tenant type * PEP-8 for echo.py * Initial auth types * Readme update * Fixed identity.py and some styling * Minor updates * Keystone WSGI and eventlet * Corrected how to run echo service * Replaced paster with eventlet for echo service * Added create tables in README and modified keystone.db to reflect the new schema * Merged identity functions second time * Sync * Whoops should have never checked this in * all management files except user add and delete from group * Management files except for add/delete user from group * Updated README * Setup PasteDeploy and configured PAPIAuth * reorganization of files * Add SOAPUI projects * Resolved Conflicts * Removed Conflicts * dos2unix * Deleted IDE files * Importing from DevTeam * Import from DevTeam * updates DevTeam * Code by Dev Team * Added Power API Auth Middleware * removed unused libraries * Dev Team: validate_token , create_user ( created for test purpose) and update_tenant * Added to README * Fixed bug in echo.py * Whoops forgot auth header * Instructions for soapUI * Add WADL links for convenience * Initial work into paste deploy...commen out for now * Added echo.wadl * Fixed for case with missing accept header * Added content nagotiation * Use XSL to convert * Better quote handling * Add JSON transform * Whoops samples don't match * XSD for echo service * Initial echo service * Updates to identity.py and README * Added X-Auth-Token * Added extensions * Updated errors for extension requests * Added getTenant, updateTenant, deleteTenant * Added get and create tenants * Initial WADL with token operations * Added faults * Remove refrences to usernameConflict and groupConflict * Added common extensions * Added api.xsd schema index * Added XSD 1.1 and atom linking support * Made the tenant xsd extensible * Initial tenant xsd * Made the token schema extensible * Initial token schema * Groups should have ids instead of names? * Added Creating Tenants, JSON only * Remove mention of service catalog * Updated samples * Updated pubdate * Updates to intro section * Updated concepts * Better entities in document * Removed init section from docs, we'll get to them later * Added Dependencies section * Added License & Create/Delete user management CLI * Initial docs import * Created DB with users table, simple schema * first commit keystone-2014.1/doc/0000775000175400017540000000000012323716511015346 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/ext/0000775000175400017540000000000012323716511016146 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/ext/apidoc.py0000664000175400017540000000301012323716267017761 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. # NOTE(dstanek): Uncomment the [pbr] section in setup.cfg and remove this # Sphinx extension when https://launchpad.net/bugs/1260495 is fixed. import os.path as path from sphinx import apidoc # NOTE(dstanek): pbr will run Sphinx multiple times when it generates # documentation. Once for each builder. To run this extension we use the # 'builder-inited' hook that fires at the beginning of a Sphinx build. # We use ``run_already`` to make sure apidocs are only generated once # even if Sphinx is run multiple times. run_already = False def run_apidoc(app): global run_already if run_already: return run_already = True package_dir = path.abspath(path.join(app.srcdir, '..', '..', 'keystone')) source_dir = path.join(app.srcdir, 'api') apidoc.main(['apidoc', package_dir, '-f', '-H', 'Keystone Modules', '-o', source_dir]) def setup(app): app.connect('builder-inited', run_apidoc) keystone-2014.1/doc/ext/__init__.py0000664000175400017540000000000012323716267020255 0ustar jenkinsjenkins00000000000000keystone-2014.1/doc/README.rst0000664000175400017540000000034612323716267017050 0ustar jenkinsjenkins00000000000000Building Docs ============= Developer documentation is generated using Sphinx. To build this documentation, run the following from the root of the repository:: $ tox -e docs The documentation will be built at ``doc/build/``. keystone-2014.1/doc/Makefile0000664000175400017540000001317112323716267017021 0ustar jenkinsjenkins00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build SOURCEDIR = source SPHINXAPIDOC = sphinx-apidoc # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " autodoc generate the autodoc templates" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* autodoc: $(SPHINXAPIDOC) -f -o $(SOURCEDIR) ../keystone html: autodoc $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/keystone.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/keystone.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/keystone" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/keystone" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." keystone-2014.1/doc/source/0000775000175400017540000000000012323716511016646 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/source/configuration.rst0000664000175400017540000015257412323716267022275 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ==================== Configuring Keystone ==================== .. toctree:: :maxdepth: 1 man/keystone-manage man/keystone-all Once Keystone is installed, it is configured via a primary configuration file (``etc/keystone.conf``), a PasteDeploy configuration file (``etc/keystone-paste.ini``), possibly a separate logging configuration file, and initializing data into Keystone using the command line client. Starting and Stopping Keystone ============================== Start Keystone services using the command:: $ keystone-all Invoking this command starts up two ``wsgi.Server`` instances, ``admin`` (the administration API) and ``main`` (the primary/public API interface). Both services are configured to run in a single process. Stop the process using ``Control-C``. .. NOTE:: If you have not already configured Keystone, it may not start as expected. Configuration Files =================== The Keystone configuration files are an ``ini`` file format based on Paste_, a common system used to configure Python WSGI based applications. The PasteDeploy configuration entries (WSGI pipeline definitions) can be provided in a separate ``keystone-paste.ini`` file, while general and driver-specific configuration parameters are in the primary configuration file ``keystone.conf``. The primary configuration file is organized into the following sections: * ``[DEFAULT]`` - general configuration * ``[sql]`` - optional storage backend configuration * ``[ec2]`` - Amazon EC2 authentication driver configuration * ``[s3]`` - Amazon S3 authentication driver configuration. * ``[oauth1]`` - Oauth 1.0a system driver configuration * ``[identity]`` - identity system driver configuration * ``[catalog]`` - service catalog driver configuration * ``[token]`` - token driver & token provider configuration * ``[cache]`` - caching layer configuration * ``[policy]`` - policy system driver configuration for RBAC * ``[signing]`` - cryptographic signatures for PKI based tokens * ``[ssl]`` - SSL configuration * ``[auth]`` - Authentication plugin configuration * ``[os_inherit]`` - Inherited Role Assignment extension * ``[endpoint_filter]`` - Endpoint Filtering extension configuration * ``[paste_deploy]`` - Pointer to the PasteDeploy configuration file * ``[federation]`` - Federation driver configuration The Keystone primary configuration file is expected to be named ``keystone.conf``. When starting Keystone, you can specify a different configuration file to use with ``--config-file``. If you do **not** specify a configuration file, Keystone will look in the following directories for a configuration file, in order: * ``~/.keystone/`` * ``~/`` * ``/etc/keystone/`` * ``/etc/`` PasteDeploy configuration file is specified by the ``config_file`` parameter in ``[paste_deploy]`` section of the primary configuration file. If the parameter is not an absolute path, then Keystone looks for it in the same directories as above. If not specified, WSGI pipeline definitions are loaded from the primary configuration file. Domain-specific Drivers ----------------------- .. WARNING:: This feature is experimental and unsupported in Havana (with several known issues that will not be fixed). Feedback welcome for Icehouse! Keystone supports the option (disabled by default) to specify identity driver configurations on a domain by domain basis, allowing, for example, a specific domain to have its own LDAP or SQL server. This is configured by specifying the following options:: [identity] domain_specific_drivers_enabled = True domain_config_dir = /etc/keystone/domains Setting ``domain_specific_drivers_enabled`` to ``True`` will enable this feature, causing Keystone to look in the ``domain_config_dir`` for config files of the form:: keystone..conf Options given in the domain specific configuration file will override those in the primary configuration file for the specified domain only. Domains without a specific configuration file will continue to use the options from the primary configuration file. Authentication Plugins ---------------------- Keystone supports authentication plugins and they are specified in the ``[auth]`` section of the configuration file. However, an authentication plugin may also have its own section in the configuration file. It is up to the plugin to register its own configuration options. * ``methods`` - comma-delimited list of authentication plugin names * ```` - specify the class which handles to authentication method, in the same manner as one would specify a backend driver. Keystone provides three authentication methods by default. ``password`` handles password authentication and ``token`` handles token authentication. ``external`` is used in conjunction with authentication performed by a container web server that sets the ``REMOTE_USER`` environment variable. For more details, refer to :doc:`External Authentication `. How to Implement an Authentication Plugin ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ All authentication plugins must extend the ``keystone.auth.core.AuthMethodHandler`` class and implement the ``authenticate()`` method. The ``authenticate()`` method expects the following parameters. * ``context`` - Keystone's request context * ``auth_payload`` - the content of the authentication for a given method * ``auth_context`` - user authentication context, a dictionary shared by all plugins. It contains ``method_names`` and ``extras`` by default. ``method_names`` is a list and ``extras`` is a dictionary. If successful, the ``authenticate()`` method must provide a valid ``user_id`` in ``auth_context`` and return ``None``. ``method_name`` is used to convey any additional authentication methods in case authentication is for re-scoping. For example, if the authentication is for re-scoping, a plugin must append the previous method names into ``method_names``. Also, a plugin may add any additional information into ``extras``. Anything in ``extras`` will be conveyed in the token's ``extras`` field. If authentication requires multiple steps, the ``authenticate()`` method must return the payload in the form of a dictionary for the next authentication step. If authentication is unsuccessful, the ``authenticate()`` method must raise a ``keystone.exception.Unauthorized`` exception. Simply add the new plugin name to the ``methods`` list along with your plugin class configuration in the ``[auth]`` sections of the configuration file to deploy it. If the plugin require addition configurations, it may register its own section in the configuration file. Plugins are invoked in the order in which they are specified in the ``methods`` attribute of the ``authentication`` request body. If multiple plugins are invoked, all plugins must succeed in order to for the entire authentication to be successful. Furthermore, all the plugins invoked must agree on the ``user_id`` in the ``auth_context``. The ``REMOTE_USER`` environment variable is only set from a containing webserver. However, to ensure that a user must go through other authentication mechanisms, even if this variable is set, remove ``external`` from the list of plugins specified in ``methods``. This effectively disables external authentication. For more details, refer to :doc:`External Authentication `. Token Provider -------------- Keystone supports customizable token provider and it is specified in the ``[token]`` section of the configuration file. Keystone provides both UUID and PKI token providers, with PKI token provider enabled as default. However, users may register their own token provider by configuring the following property. * ``provider`` - token provider driver. Defaults to ``keystone.token.providers.pki.Provider`` Note that ``token_format`` in the ``[signing]`` section is deprecated but still being supported for backward compatibility. Therefore, if ``provider`` is set to ``keystone.token.providers.pki.Provider``, ``token_format`` must be ``PKI``. Conversely, if ``provider`` is ``keystone.token.providers.uuid.Provider``, ``token_format`` must be ``UUID``. For a customized provider, ``token_format`` must not set to ``PKI`` or ``UUID``. PKI or UUID? ^^^^^^^^^^^^ UUID-based tokens are randomly generated opaque strings that are issued and validated by the identity service. They must be persisted by the identity service in order to be later validated, and revoking them is simply a matter of deleting them from the token persistence backend. PKI-based tokens are Cryptographic Message Syntax (CMS) strings that can be verified offline using keystone's public signing key. The only reason for them to be persisted by the identity service is to later build token revocation lists (explicit lists of tokens that have been revoked), otherwise they are theoretically ephemeral. PKI tokens should therefore have much better scaling characteristics (decentralized validation). They are base-64 encoded (and are therefore not URL-friendly without encoding) and may be too long to fit in either headers or URLs if they contain extensive service catalogs or other additional attributes. .. WARNING:: Both UUID- and PKI-based tokens are bearer tokens, meaning that they must be protected from unnecessary disclosure to prevent unauthorized access. The current architectural approaches for both UUID- and PKI-based tokens have pain points exposed by environments under heavy load (search bugs and blueprints for the latest details and potential solutions), although PKI tokens became the default configuration option in the Grizzly release. Caching Layer ------------- Keystone supports a caching layer that is above the configurable subsystems (e.g ``token``, ``identity``, etc). Keystone uses the `dogpile.cache`_ library which allows for flexible cache backends. The majority of the caching configuration options are set in the ``[cache]`` section. However, each section that has the capability to be cached usually has a ``caching`` boolean value that will toggle caching for that specific section. The current default behavior is that subsystem caching is enabled, but the global toggle is set to disabled. ``[cache]`` configuration section: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ``enabled`` - enables/disables caching across all of keystone * ``debug_cache_backend`` - enables more in-depth logging from the cache backend (get, set, delete, etc) * ``backend`` - the caching backend module to use e.g. ``dogpile.cache.memcached`` .. NOTE:: A given ``backend`` must be registered with ``dogpile.cache`` before it can be used. The default backend is the ``Keystone`` no-op backend (``keystone.common.cache.noop``). If caching is desired a different backend will need to be specified. Current functional backends are: * ``dogpile.cache.memcached`` - Memcached backend using the standard `python-memcached`_ library * ``dogpile.cache.pylibmc`` - Memcached backend using the `pylibmc`_ library * ``dogpile.cache.bmemcached`` - Memcached using `python-binary-memcached`_ library. * ``dogpile.cache.redis`` - `Redis`_ backend * ``dogpile.cache.dbm`` - local DBM file backend * ``dogpile.cache.memory`` - in-memory cache * ``keystone.cache.mongo`` - MongoDB as caching backend .. WARNING:: ``dogpile.cache.memory`` is not suitable for use outside of unit testing as it does not cleanup it's internal cache on cache expiration, does not provide isolation to the cached data (values in the store can be inadvertently changed without extra layers of data protection added), and does not share cache between processes. This means that caching and cache invalidation will not be consistent or reliable when using ``Keystone`` and the ``dogpile.cache.memory`` backend under any real workload. * ``expiration_time`` - int, the default length of time to cache a specific value. A value of ``0`` indicates to not cache anything. It is recommended that the ``enabled`` option be used to disable cache instead of setting this to ``0``. * ``backend_argument`` - an argument passed to the backend when instantiated ``backend_argument`` should be specified once per argument to be passed to the back end and in the format of ``:``. e.g.: ``backend_argument = host:localhost`` * ``proxies`` - comma delimited list of `ProxyBackends`_ e.g. ``my.example.Proxy, my.example.Proxy2`` * ``use_key_mangler`` - Use a key-mangling function (sha1) to ensure fixed length cache-keys. This is toggle-able for debugging purposes, it is highly recommended to always leave this set to True. If the cache backend provides a key-mangler, this option has no effect. Current keystone systems that have caching capabilities: * ``token`` The token system has a separate ``cache_time`` configuration option, that can be set to a value above or below the global ``expiration_time`` default, allowing for different caching behavior from the other systems in ``Keystone``. This option is set in the ``[token]`` section of the configuration file. The Token Revocation List cache time is handled by the configuration option ``revocation_cache_time`` in the ``[token]`` section. The revocation list is refreshed whenever a token is revoked. It typically sees significantly more requests than specific token retrievals or token validation calls. * ``assignment`` The assignment system has a separate ``cache_time`` configuration option, that can be set to a value above or below the global ``expiration_time`` default, allowing for different caching behavior from the other systems in ``Keystone``. This option is set in the ``[assignment]`` section of the configuration file. Currently ``assignment`` has caching for ``project``, ``domain``, and ``role`` specific requests (primarily around the CRUD actions). Caching is currently not implemented on grants. The list (``list_projects``, ``list_domains``, etc) methods are not subject to caching. .. WARNING:: Be aware that if a read-only ``assignment`` backend is in use, the cache will not immediately reflect changes on the back end. Any given change may take up to the ``cache_time`` (if set in the ``[assignment]`` section of the configuration) or the global ``expiration_time`` (set in the ``[cache]`` section of the configuration) before it is reflected. If this type of delay (when using a read-only ``assignment`` backend) is an issue, it is recommended that caching be disabled on ``assignment``. To disable caching specifically on ``assignment``, in the ``[assignment]`` section of the configuration set ``caching`` to ``False``. For more information about the different backends (and configuration options): * `dogpile.cache.backends.memory`_ * `dogpile.cache.backends.memcached`_ * `dogpile.cache.backends.redis`_ * `dogpile.cache.backends.file`_ * :mod:`keystone.common.cache.backends.mongo` .. _`dogpile.cache`: http://dogpilecache.readthedocs.org/en/latest/ .. _`python-memcached`: http://www.tummy.com/software/python-memcached/ .. _`pylibmc`: http://sendapatch.se/projects/pylibmc/index.html .. _`python-binary-memcached`: https://github.com/jaysonsantos/python-binary-memcached .. _`Redis`: http://redis.io/ .. _`dogpile.cache.backends.memory`: http://dogpilecache.readthedocs.org/en/latest/api.html#memory-backend .. _`dogpile.cache.backends.memcached`: http://dogpilecache.readthedocs.org/en/latest/api.html#memcached-backends .. _`dogpile.cache.backends.redis`: http://dogpilecache.readthedocs.org/en/latest/api.html#redis-backends .. _`dogpile.cache.backends.file`: http://dogpilecache.readthedocs.org/en/latest/api.html#file-backends .. _`ProxyBackends`: http://dogpilecache.readthedocs.org/en/latest/api.html#proxy-backends .. _`PyMongo API`: http://api.mongodb.org/python/current/api/pymongo/index.html Certificates for PKI -------------------- PKI stands for Public Key Infrastructure. Tokens are documents, cryptographically signed using the X509 standard. In order to work correctly token generation requires a public/private key pair. The public key must be signed in an X509 certificate, and the certificate used to sign it must be available as Certificate Authority (CA) certificate. These files can be generated either using the keystone-manage utility, or externally generated. The files need to be in the locations specified by the top level Keystone configuration file as specified in the above section. Additionally, the private key should only be readable by the system user that will run Keystone. The values that specify where to read the certificates are under the ``[signing]`` section of the configuration file. The configuration values are: * ``token_format`` - Determines the algorithm used to generate tokens. Can be either ``UUID`` or ``PKI``. Defaults to ``PKI``. This option must be used in conjunction with ``provider`` configuration in the ``[token]`` section. * ``certfile`` - Location of certificate used to verify tokens. Default is ``/etc/keystone/ssl/certs/signing_cert.pem`` * ``keyfile`` - Location of private key used to sign tokens. Default is ``/etc/keystone/ssl/private/signing_key.pem`` * ``ca_certs`` - Location of certificate for the authority that issued the above certificate. Default is ``/etc/keystone/ssl/certs/ca.pem`` * ``ca_key`` - Default is ``/etc/keystone/ssl/private/cakey.pem`` * ``key_size`` - Default is ``2048`` * ``valid_days`` - Default is ``3650`` Signing Certificate Issued by External CA ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You may use a signing certificate issued by an external CA instead of generated by keystone-manage. However, certificate issued by external CA must satisfy the following conditions: * all certificate and key files must be in Privacy Enhanced Mail (PEM) format * private key files must not be protected by a password When using signing certificate issued by an external CA, you do not need to specify ``key_size``, ``valid_days`` and ``ca_key`` as they will be ignored. The basic workflow for using a signing certificate issed by an external CA involves: 1. `Request Signing Certificate from External CA`_ 2. convert certificate and private key to PEM if needed 3. `Install External Signing Certificate`_ Request Signing Certificate from External CA ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One way to request a signing certificate from an external CA is to first generate a PKCS #10 Certificate Request Syntax (CRS) using OpenSSL CLI. First create a certificate request configuration file (e.g. ``cert_req.conf``):: [ req ] default_bits = 2048 default_keyfile = keystonekey.pem default_md = default prompt = no distinguished_name = distinguished_name [ distinguished_name ] countryName = US stateOrProvinceName = CA localityName = Sunnyvale organizationName = OpenStack organizationalUnitName = Keystone commonName = Keystone Signing emailAddress = keystone@openstack.org Then generate a CRS with OpenSSL CLI. **Do not encrypt the generated private key. Must use the -nodes option.** For example:: openssl req -newkey rsa:2048 -keyout signing_key.pem -keyform PEM -out signing_cert_req.pem -outform PEM -config cert_req.conf -nodes If everything is successfully, you should end up with ``signing_cert_req.pem`` and ``signing_key.pem``. Send ``signing_cert_req.pem`` to your CA to request a token signing certificate and make sure to ask the certificate to be in PEM format. Also, make sure your trusted CA certificate chain is also in PEM format. Install External Signing Certificate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Assuming you have the following already: * ``signing_cert.pem`` - (Keystone token) signing certificate in PEM format * ``signing_key.pem`` - corresponding (non-encrypted) private key in PEM format * ``cacert.pem`` - trust CA certificate chain in PEM format Copy the above to your certificate directory. For example:: mkdir -p /etc/keystone/ssl/certs cp signing_cert.pem /etc/keystone/ssl/certs/ cp signing_key.pem /etc/keystone/ssl/certs/ cp cacert.pem /etc/keystone/ssl/certs/ chmod -R 700 /etc/keystone/ssl/certs **Make sure the certificate directory is root-protected.** If your certificate directory path is different from the default ``/etc/keystone/ssl/certs``, make sure it is reflected in the ``[signing]`` section of the configuration file. Service Catalog --------------- Keystone provides two configuration options for your service catalog. SQL-based Service Catalog (``sql.Catalog``) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A dynamic database-backed driver fully supporting persistent configuration via keystoneclient administration commands (e.g. ``keystone endpoint-create``). ``keystone.conf`` example:: [catalog] driver = keystone.catalog.backends.sql.Catalog .. NOTE:: A `template_file` does not need to be defined for the sql.Catalog driver. To build your service catalog using this driver, see the built-in help:: $ keystone $ keystone help service-create $ keystone help endpoint-create You can also refer to `an example in Keystone (tools/sample_data.sh) `_. File-based Service Catalog (``templated.Catalog``) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The templated catalog is an in-memory backend initialized from a read-only ``template_file``. Choose this option only if you know that your service catalog will not change very much over time. .. NOTE:: Attempting to manage your service catalog using keystoneclient commands (e.g. ``keystone endpoint-create``) against this driver will result in ``HTTP 501 Not Implemented`` errors. This is the expected behavior. If you want to use these commands, you must instead use the SQL-based Service Catalog driver. ``keystone.conf`` example:: [catalog] driver = keystone.catalog.backends.templated.Catalog template_file = /opt/stack/keystone/etc/default_catalog.templates The value of ``template_file`` is expected to be an absolute path to your service catalog configuration. An example ``template_file`` is included in Keystone, however you should create your own to reflect your deployment. Another such example is `available in devstack (files/default_catalog.templates) `_. Logging ------- Logging is configured externally to the rest of Keystone. Configure the path to your logging configuration file using the ``[DEFAULT] log_config`` option of ``keystone.conf``. If you wish to route all your logging through syslog, set the ``[DEFAULT] use_syslog`` option. A sample ``log_config`` file is included with the project at ``etc/logging.conf.sample``. Like other OpenStack projects, Keystone uses the `python logging module`, which includes extensive configuration options for choosing the output levels and formats. .. _Paste: http://pythonpaste.org/ .. _`python logging module`: http://docs.python.org/library/logging.html Monitoring ---------- Keystone provides some basic request/response monitoring statistics out of the box. Enable data collection by defining a ``stats_monitoring`` filter and including it at the beginning of any desired WSGI pipelines:: [filter:stats_monitoring] paste.filter_factory = keystone.contrib.stats:StatsMiddleware.factory [pipeline:public_api] pipeline = stats_monitoring [...] public_service Enable the reporting of collected data by defining a ``stats_reporting`` filter and including it near the end of your ``admin_api`` WSGI pipeline (After ``*_body`` middleware and before ``*_extension`` filters is recommended):: [filter:stats_reporting] paste.filter_factory = keystone.contrib.stats:StatsExtension.factory [pipeline:admin_api] pipeline = [...] json_body stats_reporting ec2_extension [...] admin_service Query the admin API for statistics using:: $ curl -H 'X-Auth-Token: ADMIN' http://localhost:35357/v2.0/OS-STATS/stats Reset collected data using:: $ curl -H 'X-Auth-Token: ADMIN' -X DELETE http://localhost:35357/v2.0/OS-STATS/stats SSL --- Keystone may be configured to support SSL and 2-way SSL out-of-the-box. The X509 certificates used by keystone can be generated by keystone-manage or obtained externally and configured for use with Keystone as described in this section. Here is the description of each of them and their purpose: Types of certificates ^^^^^^^^^^^^^^^^^^^^^ cacert.pem Certificate Authority chain to validate against. ssl_cert.pem Public certificate for Keystone server. middleware.pem Public and private certificate for Keystone middleware/client. cakey.pem Private key for the CA. ssl_key.pem Private key for the Keystone server. Note that you may choose whatever names you want for these certificates, or combine the public/private keys in the same file if you wish. These certificates are just provided as an example. Configuration ^^^^^^^^^^^^^ To enable SSL modify the etc/keystone.conf file accordingly under the [ssl] section. SSL configuration example using the included sample certificates:: [ssl] enable = True certfile = keyfile = ca_certs = ca_key = cert_required = False * ``enable``: True enables SSL. Defaults to False. * ``certfile``: Path to Keystone public certificate file. * ``keyfile``: Path to Keystone private certificate file. If the private key is included in the certfile, the keyfile maybe omitted. * ``ca_certs``: Path to CA trust chain. * ``cert_required``: Requires client certificate. Defaults to False. When generating SSL certificates the following values are read * ``key_size``: Key size to create. Defaults to 1024. * ``valid_days``: How long the certificate is valid for. Defaults to 3650 (10 years). * ``ca_key``: The private key for the CA. Defaults to ``/etc/keystone/ssl/certs/cakey.pem``. * ``cert_subject``: The subject to set in the certificate. Defaults to /C=US/ST=Unset/L=Unset/O=Unset/CN=localhost. When setting the subject it is important to set CN to be the address of the server so client validation will succeed. This generally means having the subject be at least /CN= Generating SSL certificates ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Certificates for secure HTTP communication can be generated by:: $ keystone-manage ssl_setup This will create a private key, a public key and a certificate that will be used to encrypt communications with keystone. In the event that a Certificate Authority is not given a testing one will be created. It is likely in a production environment that these certificates will be created and provided externally. User CRUD --------- Keystone provides a user CRUD filter that can be added to the public_api pipeline. This user crud filter allows users to use a HTTP PATCH to change their own password. To enable this extension you should define a user_crud_extension filter, insert it after the ``*_body`` middleware and before the ``public_service`` app in the public_api WSGI pipeline in ``keystone-paste.ini`` e.g.:: [filter:user_crud_extension] paste.filter_factory = keystone.contrib.user_crud:CrudExtension.factory [pipeline:public_api] pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body debug ec2_extension user_crud_extension public_service Each user can then change their own password with a HTTP PATCH :: > curl -X PATCH http://localhost:5000/v2.0/OS-KSCRUD/users/ -H "Content-type: application/json" \ -H "X_Auth_Token: " -d '{"user": {"password": "ABCD", "original_password": "DCBA"}}' In addition to changing their password all of the users current tokens will be deleted (if the backend used is sql) Inherited Role Assignment Extension ----------------------------------- Keystone provides an optional extension that adds the capability to assign roles to a domain that, rather than affect the domain itself, are instead inherited to all projects owned by theat domain. This extension is disabled by default, but can be enabled by including the following in ``keystone.conf``:: [os_inherit] enabled = True Token Binding ------------- Token binding refers to the practice of embedding information from external authentication providers (like a company's Kerberos server) inside the token such that a client may enforce that the token only be used in conjunction with that specified authentication. This is an additional security mechanism as it means that if a token is stolen it will not be usable without also providing the external authentication. To activate token binding you must specify the types of authentication that token binding should be used for in ``keystone.conf`` e.g.:: [token] bind = kerberos Currently only ``kerberos`` is supported. To enforce checking of token binding the ``enforce_token_bind`` parameter should be set to one of the following modes: * ``disabled`` disable token bind checking * ``permissive`` enable bind checking, if a token is bound to a mechanism that is unknown to the server then ignore it. This is the default. * ``strict`` enable bind checking, if a token is bound to a mechanism that is unknown to the server then this token should be rejected. * ``required`` enable bind checking and require that at least 1 bind mechanism is used for tokens. * named enable bind checking and require that the specified authentication mechanism is used. e.g.:: [token] enforce_token_bind = kerberos *Do not* set ``enforce_token_bind = named`` as there is not an authentication mechanism called ``named``. Limiting the number of entities returned in a collection -------------------------------------------------------- Keystone provides a method of setting a limit to the number of entities returned in a collection, which is useful to prevent overly long response times for list queries that have not specified a sufficiently narrow filter. This limit can be set globally by setting ``list_limit`` in the default section of ``keystone.conf``, with no limit set by default. Individual driver sections may override this global value with a specific limit, for example:: [assignment] list_limit = 100 If a response to ``list_{entity}`` call has been truncated, then the response status code will still be 200 (OK), but the ``truncated`` attribute in the collection will be set to ``true``. Sample Configuration Files -------------------------- The ``etc/`` folder distributed with Keystone contains example configuration files for each Server application. * ``etc/keystone.conf.sample`` * ``etc/keystone-paste.ini`` * ``etc/logging.conf.sample`` * ``etc/default_catalog.templates`` .. _`API protection with RBAC`: Keystone API protection with Role Based Access Control (RBAC) ============================================================= Like most OpenStack projects, Keystone supports the protection of its APIs by defining policy rules based on an RBAC approach. These are stored in a JSON policy file, the name and location of which is set in the main Keystone configuration file. Each keystone v3 API has a line in the policy file which dictates what level of protection is applied to it, where each line is of the form: : or where can be contain or is a set of identifiers that must match between the token provided by the caller of the API and the parameters or target entities of the API call in question. For example: "identity:create_user": [["role:admin", "domain_id:%(user.domain_id)s"]] indicates that to create a user you must have the admin role in your token and in addition the domain_id in your token (which implies this must be a domain scoped token) must match the domain_id in the user object you are trying to create. In other words, you must have the admin role on the domain in which you are creating the user, and the token you are using must be scoped to that domain. Each component of a match statement is of the form: : or The following attributes are available * Attributes from token: user_id, the domain_id or project_id depending on the scope, and the list of roles you have within that scope * Attributes related to API call: Any parameters that are passed into the API call are available, along with any filters specified in the query string. Attributes of objects passed can be refererenced using an object.attribute syntax (e.g. user.domain_id). The target objects of an API are also available using a target.object.attribute syntax. For instance: "identity:delete_user": [["role:admin", "domain_id:%(target.user.domain_id)s"]] would ensure that the user object that is being deleted is in the same domain as the token provided. Every target object has an `id` and a `name` available as `target..id` and `target..name`. Other attributes are retrieved from the database and vary between object types. Moreover, some database fields are filtered out (e.g. user passwords). List of object attributes: * role: * target.role.id * target.role.name * user: * target.user.default_project_id * target.user.description * target.user.domain_id * target.user.enabled * target.user.id * target.user.name * group: * target.group.description * target.group.domain_id * target.group.id * target.group.name * domain: * target.domain.enabled * target.domain.id * target.domain.name * project: * target.project.description * target.project.domain_id * target.project.enabled * target.project.id * target.project.name The default policy.json file supplied provides a somewhat basic example of API protection, and does not assume any particular use of domains. For multi-domain configuration installations where, for example, a cloud provider wishes to allow adminsistration of the contents of a domain to be delegated, it is recommended that the supplied policy.v3cloudsample.json is used as a basis for creating a suitable production policy file. This example policy file also shows the use of an admin_domain to allow a cloud provider to enable cloud adminstrators to have wider access across the APIs. A clean installation would need to perhaps start with the standard policy file, to allow creation of the admin_domain with the first users within it. The domain_id of the admin domain would then be obtained and could be pasted into a modifed version of policy.v3cloudsample.json which could then be enabled as the main policy file. .. _`adding extensions`: Adding Extensions ================= OAuth1.0a --------- .. toctree:: :maxdepth: 1 extensions/oauth1-configuration.rst Endpoint Filtering ------------------ .. toctree:: :maxdepth: 1 extensions/endpoint_filter-configuration.rst Federation ---------- .. toctree:: :maxdepth: 1 extensions/federation-configuration.rst Revocation Events ------------------ .. toctree:: :maxdepth: 1 extensions/revoke-configuration.rst .. _`prepare your deployment`: Preparing your deployment ========================= Step 1: Configure keystone.conf ------------------------------- Ensure that your ``keystone.conf`` is configured to use a SQL driver:: [identity] driver = keystone.identity.backends.sql.Identity You may also want to configure your ``[sql]`` settings to better reflect your environment:: [sql] connection = sqlite:///keystone.db idle_timeout = 200 .. NOTE:: It is important that the database that you specify be different from the one containing your existing install. Step 2: Sync your new, empty database ------------------------------------- You should now be ready to initialize your new database without error, using:: $ keystone-manage db_sync To test this, you should now be able to start ``keystone-all`` and use the Keystone Client to list your tenants (which should successfully return an empty list from your new database):: $ keystone --os-token ADMIN --os-endpoint http://127.0.0.1:35357/v2.0/ tenant-list +----+------+---------+ | id | name | enabled | +----+------+---------+ +----+------+---------+ .. NOTE:: We're providing the default OS_SERVICE_TOKEN and OS_SERVICE_ENDPOINT values from ``keystone.conf`` to connect to the Keystone service. If you changed those values, or deployed Keystone to a different endpoint, you will need to change the provided command accordingly. Initializing Keystone ===================== ``keystone-manage`` is designed to execute commands that cannot be administered through the normal REST API. At the moment, the following calls are supported: * ``db_sync``: Sync the database schema. * ``pki_setup``: Initialize the certificates for PKI based tokens. * ``ssl_setup``: Generate certificates for HTTPS. Invoking ``keystone-manage`` by itself will give you additional usage information. The private key used for token signing can only be read by its owner. This prevents unauthorized users from spuriously signing tokens. ``keystone-manage pki_setup`` Should be run as the same system user that will be running the Keystone service to ensure proper ownership for the private key file and the associated certificates. Adding Users, Tenants, and Roles with python-keystoneclient =========================================================== User, tenants, and roles must be administered using admin credentials. There are two ways to configure ``python-keystoneclient`` to use admin credentials, using the either an existing token or password credentials. Authenticating with a Token --------------------------- .. NOTE:: If your Keystone deployment is brand new, you will need to use this authentication method, along with your ``[DEFAULT] admin_token``. To use Keystone with a token, set the following flags: * ``--os-endpoint OS_SERVICE_ENDPOINT``: allows you to specify the Keystone endpoint to communicate with. The default endpoint is ``http://localhost:35357/v2.0`` * ``--os-token OS_SERVICE_TOKEN``: your service token To administer a Keystone endpoint, your token should be either belong to a user with the ``admin`` role, or, if you haven't created one yet, should be equal to the value defined by ``[DEFAULT] admin_token`` in your ``keystone.conf``. You can also set these variables in your environment so that they do not need to be passed as arguments each time:: $ export OS_SERVICE_ENDPOINT=http://localhost:35357/v2.0 $ export OS_SERVICE_TOKEN=ADMIN Authenticating with a Password ------------------------------ To administer a Keystone endpoint, the following user referenced below should be granted the ``admin`` role. * ``--os_username OS_USERNAME``: Name of your user * ``--os_password OS_PASSWORD``: Password for your user * ``--os_tenant_name OS_TENANT_NAME``: Name of your tenant * ``--os_auth_url OS_AUTH_URL``: URL of your Keystone auth server, e.g. ``http://localhost:35357/v2.0`` You can also set these variables in your environment so that they do not need to be passed as arguments each time:: $ export OS_USERNAME=my_username $ export OS_PASSWORD=my_password $ export OS_TENANT_NAME=my_tenant Example usage ------------- ``keystone`` is set up to expect commands in the general form of ``keystone`` ``command`` ``argument``, followed by flag-like keyword arguments to provide additional (often optional) information. For example, the command ``user-list`` and ``tenant-create`` can be invoked as follows:: # Using token auth env variables export OS_SERVICE_ENDPOINT=http://127.0.0.1:35357/v2.0/ export OS_SERVICE_TOKEN=secrete_token keystone user-list keystone tenant-create --name=demo # Using token auth flags keystone --os-token=secrete --os-endpoint=http://127.0.0.1:35357/v2.0/ user-list keystone --os-token=secrete --os-endpoint=http://127.0.0.1:35357/v2.0/ tenant-create --name=demo # Using user + password + tenant_name env variables export OS_USERNAME=admin export OS_PASSWORD=secrete export OS_TENANT_NAME=admin keystone user-list keystone tenant-create --name=demo # Using user + password + tenant_name flags keystone --os_username=admin --os_password=secrete --os_tenant_name=admin user-list keystone --os_username=admin --os_password=secrete --os_tenant_name=admin tenant-create --name=demo Tenants ------- Tenants are the high level grouping within Keystone that represent groups of users. A tenant is the grouping that owns virtual machines within Nova, or containers within Swift. A tenant can have zero or more users, Users can be associated with more than one tenant, and each tenant - user pairing can have a role associated with it. ``tenant-create`` ^^^^^^^^^^^^^^^^^ keyword arguments * name * description (optional, defaults to None) * enabled (optional, defaults to True) example:: $ keystone tenant-create --name=demo creates a tenant named "demo". ``tenant-delete`` ^^^^^^^^^^^^^^^^^ arguments * tenant_id example:: $ keystone tenant-delete f2b7b39c860840dfa47d9ee4adffa0b3 Users ----- ``user-create`` ^^^^^^^^^^^^^^^ keyword arguments * name * pass * email * tenant_id (optional, defaults to None) * enabled (optional, defaults to True) example:: $ keystone user-create --name=admin \ --pass=secrete \ --tenant_id=2395953419144b67955ac4bab96b8fd2 \ --email=admin@example.com ``user-delete`` ^^^^^^^^^^^^^^^ keyword arguments * user_id example:: $ keystone user-delete f2b7b39c860840dfa47d9ee4adffa0b3 ``user-list`` ^^^^^^^^^^^^^ list users in the system, optionally by a specific tenant (identified by tenant_id) arguments * tenant_id (optional, defaults to None) example:: $ keystone user-list ``user-update`` ^^^^^^^^^^^^^^^^^^^^^ arguments * user_id keyword arguments * name Desired new user name (Optional) * email Desired new email address (Optional) * enabled Enable or disable user (Optional) example:: $ keystone user-update 03c84b51574841ba9a0d8db7882ac645 --email=newemail@example.com ``user-password-update`` ^^^^^^^^^^^^^^^^^^^^^^^^ arguments * user_id * password example:: $ keystone user-password-update --pass foo 03c84b51574841ba9a0d8db7882ac645 Roles ----- ``role-create`` ^^^^^^^^^^^^^^^ arguments * name example:: $ keystone role-create --name=demo ``role-delete`` ^^^^^^^^^^^^^^^ arguments * role_id example:: $ keystone role-delete 19d1d3344873464d819c45f521ff9890 ``role-list`` ^^^^^^^^^^^^^ example:: $ keystone role-list ``role-get`` ^^^^^^^^^^^^ arguments * role_id example:: $ keystone role-get 19d1d3344873464d819c45f521ff9890 ``user-role-add`` ^^^^^^^^^^^^^^^^^ keyword arguments * user * role * tenant_id example:: $ keystone user-role-add \ --user=96a6ebba0d4c441887aceaeced892585 \ --role=f8dd5a2e4dc64a41b96add562d9a764e \ --tenant_id=2395953419144b67955ac4bab96b8fd2 ``user-role-remove`` ^^^^^^^^^^^^^^^^^^^^ keyword arguments * user * role * tenant_id example:: $ keystone user-role-remove \ --user=96a6ebba0d4c441887aceaeced892585 \ --role=f8dd5a2e4dc64a41b96add562d9a764e \ --tenant_id=2395953419144b67955ac4bab96b8fd2 Services -------- ``service-create`` ^^^^^^^^^^^^^^^^^^ keyword arguments * name * type * description example:: $ keystone service-create \ --name=nova \ --type=compute \ --description="Nova Compute Service" ``service-list`` ^^^^^^^^^^^^^^^^ arguments * service_id example:: $ keystone service-list ``service-get`` ^^^^^^^^^^^^^^^ arguments * service_id example:: $ keystone service-get 08741d8ed88242ca88d1f61484a0fe3b ``service-delete`` ^^^^^^^^^^^^^^^^^^ arguments * service_id example:: $ keystone service-delete 08741d8ed88242ca88d1f61484a0fe3b Removing Expired Tokens =========================================================== In the SQL backend expired tokens are not automatically removed. These tokens can be removed with:: $ keystone-manage token_flush The memcache backend automatically discards expired tokens and so flushing is unnecessary and if attempted will fail with a NotImplemented error. Configuring the LDAP Identity Provider =========================================================== As an alternative to the SQL Database backing store, Keystone can use a directory server to provide the Identity service. An example Schema for openstack would look like this:: dn: dc=openstack,dc=org dc: openstack objectClass: dcObject objectClass: organizationalUnit ou: openstack dn: ou=Projects,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: groups dn: ou=Users,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: users dn: ou=Roles,dc=openstack,dc=org objectClass: top objectClass: organizationalUnit ou: roles The corresponding entries in the Keystone configuration file are:: [ldap] url = ldap://localhost user = dc=Manager,dc=openstack,dc=org password = badpassword suffix = dc=openstack,dc=org use_dumb_member = False allow_subtree_delete = False user_tree_dn = ou=Users,dc=openstack,dc=org user_objectclass = inetOrgPerson tenant_tree_dn = ou=Projects,dc=openstack,dc=org tenant_objectclass = groupOfNames role_tree_dn = ou=Roles,dc=openstack,dc=org role_objectclass = organizationalRole The default object classes and attributes are intentionally simplistic. They reflect the common standard objects according to the LDAP RFCs. However, in a live deployment, the correct attributes can be overridden to support a preexisting, more complex schema. For example, in the user object, the objectClass posixAccount from RFC2307 is very common. If this is the underlying objectclass, then the *uid* field should probably be *uidNumber* and *username* field either *uid* or *cn*. To change these two fields, the corresponding entries in the Keystone configuration file are:: [ldap] user_id_attribute = uidNumber user_name_attribute = cn There is a set of allowed actions per object type that you can modify depending on your specific deployment. For example, the users are managed by another tool and you have only read access, in such case the configuration is:: [ldap] user_allow_create = False user_allow_update = False user_allow_delete = False tenant_allow_create = True tenant_allow_update = True tenant_allow_delete = True role_allow_create = True role_allow_update = True role_allow_delete = True There are some configuration options for filtering users, tenants and roles, if the backend is providing too much output, in such case the configuration will look like:: [ldap] user_filter = (memberof=CN=openstack-users,OU=workgroups,DC=openstack,DC=org) tenant_filter = role_filter = In case that the directory server does not have an attribute enabled of type boolean for the user, there is several configuration parameters that can be used to extract the value from an integer attribute like in Active Directory:: [ldap] user_enabled_attribute = userAccountControl user_enabled_mask = 2 user_enabled_default = 512 In this case the attribute is an integer and the enabled attribute is listed in bit 1, so the if the mask configured *user_enabled_mask* is different from 0, it gets the value from the field *user_enabled_attribute* and it makes an ADD operation with the value indicated on *user_enabled_mask* and if the value matches the mask then the account is disabled. It also saves the value without mask to the user identity in the attribute *enabled_nomask*. This is needed in order to set it back in case that we need to change it to enable/disable a user because it contains more information than the status like password expiration. Last setting *user_enabled_mask* is needed in order to create a default value on the integer attribute (512 = NORMAL ACCOUNT on AD) In case of Active Directory the classes and attributes could not match the specified classes in the LDAP module so you can configure them like:: [ldap] user_objectclass = person user_id_attribute = cn user_name_attribute = cn user_mail_attribute = mail user_enabled_attribute = userAccountControl user_enabled_mask = 2 user_enabled_default = 512 user_attribute_ignore = tenant_id,tenants tenant_objectclass = groupOfNames tenant_id_attribute = cn tenant_member_attribute = member tenant_name_attribute = ou tenant_desc_attribute = description tenant_enabled_attribute = extensionName tenant_attribute_ignore = role_objectclass = organizationalRole role_id_attribute = cn role_name_attribute = ou role_member_attribute = roleOccupant role_attribute_ignore = Enabled Emulation ----------------- Some directory servers do not provide any enabled attribute. For these servers, the ``user_enabled_emulation`` and ``tenant_enabled_emulation`` attributes have been created. They are enabled by setting their respective flags to True. Then the attributes ``user_enabled_emulation_dn`` and ``tenant_enabled_emulation_dn`` may be set to specify how the enabled users and projects (tenants) are selected. These attributes work by using a ``groupOfNames`` and adding whichever users or projects (tenants) that you want enabled to the respective group. For example, this will mark any user who is a member of ``enabled_users`` as enabled:: [ldap] user_enabled_emulation = True user_enabled_emulation_dn = cn=enabled_users,cn=groups,dc=openstack,dc=org The default values for user and project (tenant) enabled emulation DN is ``cn=enabled_users,$user_tree_dn`` and ``cn=enabled_tenants,$tenant_tree_dn`` respectively. Secure Connection ----------------- If you are using a directory server to provide the Identity service, it is strongly recommended that you utilize a secure connection from Keystone to the directory server. In addition to supporting ldaps, Keystone also provides Transport Layer Security (TLS) support. There are some basic configuration options for enabling TLS, identifying a single file or directory that contains certificates for all the Certificate Authorities that the Keystone LDAP client will recognize, and declaring what checks the client should perform on server certificates. This functionality can easily be configured as follows:: [ldap] use_tls = True tls_cacertfile = /etc/keystone/ssl/certs/cacert.pem tls_cacertdir = /etc/keystone/ssl/certs/ tls_req_cert = demand A few points worth mentioning regarding the above options. If both tls_cacertfile and tls_cacertdir are set then tls_cacertfile will be used and tls_cacertdir is ignored. Furthermore, valid options for tls_req_cert are demand, never, and allow. These correspond to the standard options permitted by the TLS_REQCERT TLS option. Read Only LDAP -------------- Many environments typically have user and group information in directories that are accessible by LDAP. This information is for read-only use in a wide array of applications. Prior to the Havana release, we could not deploy Keystone with read-only directories as backends because Keystone also needed to store information such as projects, roles, domains and role assignments into the directories in conjunction with reading user and group information. Keystone now provides an option whereby these read-only directories can be easily integrated as it now enables its identity entities (which comprises users, groups, and group memberships) to be served out of directories while assignments (which comprises projects, roles, role assignments, and domains) are to be served from a different Keystone backend (i.e. SQL). To enable this option, you must have the following ``keystone.conf`` options set:: [identity] driver = keystone.identity.backends.ldap.Identity [assignment] driver = keystone.assignment.backends.sql.Assignment With the above configuration, Keystone will only lookup identity related information such users, groups, and group membership from the directory, while assignment related information will be provided by the SQL backend. Also note that if there is an LDAP Identity, and no assignment backend is specified, the assignment backend will default to LDAP. Although this may seem counterintuitive, it is provided for backwards compatibility. Nonetheless, the explicit option will always override the implicit option, so specifying the options as shown above will always be correct. Finally, it is also worth noting that whether or not the LDAP accessible directory is to be considered read only is still configured as described in a previous section above by setting values such as the following in the ``[ldap]`` configuration section:: [ldap] user_allow_create = False user_allow_update = False user_allow_delete = False keystone-2014.1/doc/source/setup.rst0000664000175400017540000001243212323716267020552 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ============================================= Setting up a Keystone development environment ============================================= This document describes getting the source from keystone's `GitHub repository`_ for development purposes. To install keystone from packaging, refer instead to Keystone's `User Documentation`_. .. _`GitHub Repository`: http://github.com/openstack/keystone .. _`User Documentation`: http://docs.openstack.org/ Prerequisites ============= This document assumes you are using: - Ubuntu 12.04, Fedora 15, or Mac OS X Lion - `Python 2.7`_ .. _`Python 2.7`: http://www.python.org/ And that you have the following tools available on your system: - git_ - setuptools_ - pip_ **Reminder**: If you're successfully using a different platform, or a different version of the above, please document your configuration here! .. _git: http://git-scm.com/ .. _setuptools: http://pypi.python.org/pypi/setuptools Getting the latest code ======================= Make a clone of the code from our `Github repository`:: $ git clone https://github.com/openstack/keystone.git When that is complete, you can:: $ cd keystone Installing dependencies ======================= Keystone maintains two lists of dependencies:: requirements.txt test-requirements.txt The first is the list of dependencies needed for running keystone, the second list includes dependencies used for active development and testing of keystone itself. These dependencies can be installed from PyPi_ using the python tool pip_. .. _PyPi: http://pypi.python.org/ .. _pip: http://pypi.python.org/pypi/pip However, your system *may* need additional dependencies that `pip` (and by extension, PyPi) cannot satisfy. These dependencies should be installed prior to using `pip`, and the installation method may vary depending on your platform. Ubuntu 12.04:: $ sudo apt-get install python-dev libxml2-dev libxslt1-dev libsasl2-dev libsqlite3-dev libssl-dev libldap2-dev libffi-dev Fedora 15:: $ sudo yum install python-sqlite2 python-lxml python-greenlet-devel python-ldap Mac OS X Lion (requires MacPorts_):: $ sudo port install py-ldap .. _MacPorts: http://www.macports.org/ PyPi Packages and VirtualEnv ---------------------------- We recommend establishing a virtualenv to run keystone within. Virtualenv limits the python environment to just what you're installing as depdendencies, useful to keep a clean environment for working on Keystone. The tools directory in keystone has a script already created to make this very simple:: $ python tools/install_venv.py This will create a local virtual environment in the directory ``.venv``. Once created, you can activate this virtualenv for your current shell using:: $ source .venv/bin/activate The virtual environment can be disabled using the command:: $ deactivate You can also use ``tools\with_venv.sh`` to prefix commands so that they run within the virtual environment. For more information on virtual environments, see virtualenv_. .. _virtualenv: http://www.virtualenv.org/ If you want to run keystone outside of a virtualenv, you can install the dependencies directly into your system from the requires files:: # Install the dependencies for running keystone $ pip install -r requirements.txt # Install the dependencies for developing, testing, and running keystone $ pip install -r test-requirements.txt # Use python setup.py to link Keystone into python's site-packages $ python setup.py develop Verifying Keystone is set up ============================ Once set up, either directly or within a virtualenv, you should be able to invoke python and import the libraries. If you're using a virtualenv, don't forget to activate it:: $ source .venv/bin/activate $ python You should then be able to `import keystone` from your Python shell without issue:: >>> import keystone >>> If you can import keystone successfully, you should be ready to move on to :doc:`developing`. Troubleshooting =============== Eventlet segfaults on RedHat / Fedora ------------------------------------- [*If this is no longer an issue, please remove this section, thanks!*] On some OSes, specifically Fedora 15, the current versions of greenlet/eventlet segfault when running keystone. To fix this, install the development versions of greenlet and eventlet:: $ pip uninstall greenlet eventlet $ cd $ hg clone https://bitbucket.org/ambroff/greenlet $ cd greenlet $ sudo python setup.py install $ cd $ hg clone https://bitbucket.org/which_linden/eventlet $ cd greenlet $ sudo python setup.py install keystone-2014.1/doc/source/community.rst0000664000175400017540000000752712323716267021447 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ================ Getting Involved ================ The OpenStack community is a very friendly group and there are places online to join in with the community. Feel free to ask questions. This document points you to some of the places where you can communicate with people. How to Join the Community ========================= Our community welcomes all people interested in open source cloud computing, and there are no formal membership requirements. The best way to join the community is to talk with others online or at a meetup and offer contributions through Launchpad_, the wiki_, or blogs. We welcome all types of contributions, from blueprint designs to documentation to testing to deployment scripts. .. _Launchpad: https://launchpad.net/keystone .. _wiki: http://wiki.openstack.org/ #openstack on Freenode IRC Network ---------------------------------- There is a very active chat channel at ``_. This is usually the best place to ask questions and find your way around. IRC stands for Internet Relay Chat and it is a way to chat online in real time. You can also ask a question and come back to the log files to read the answer later. Logs for the #openstack IRC channel are stored at ``_. OpenStack Wiki -------------- The wiki is a living source of knowledge. It is edited by the community, and has collections of links and other sources of information. Typically the pages are a good place to write drafts for specs or documentation, describe a blueprint, or collaborate with others. `OpenStack Wiki `_ * `useful keystone project links `_ Keystone on Launchpad --------------------- Launchpad is a code hosting that OpenStack is using to track bugs, feature work, and releases of OpenStack. Like other OpenStack projects, Keystone source code is hosted on GitHub * `Keystone Project Page on Launchpad `_ * `Keystone Source Repository on GitHub `_ Within launchpad, we use `blueprints `_, to track feature work, and track `bugs `_ as well. If you are looking for a place to get started contributing to keystone, please look at any bugs for keystone that are tagged as `low-hanging-fruit `_. OpenStack Blog -------------- The OpenStack blog includes a weekly newsletter that aggregates OpenStack news from around the internet, as well as providing inside information on upcoming events and posts from OpenStack contributors. `OpenStack Blog `_ See also: `Planet OpenStack `_, an aggregation of blogs about OpenStack from around the internet, combined into a web site and RSS feed. If you'd like to contribute with your blog posts, there are instructions for `adding your blog `_. Twitter ------- Because all the cool kids do it: `@openstack `_. Also follow the `#openstack `_ tag for relevant tweets. keystone-2014.1/doc/source/architecture.rst0000664000175400017540000002156712323716267022105 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. Keystone Architecture ===================== Much of the design is precipitated from the expectation that the auth backends for most deployments will actually be shims in front of existing user systems. ------------ The Services ------------ Keystone is organized as a group of internal services exposed on one or many endpoints. Many of these services are used in a combined fashion by the frontend, for example an authenticate call will validate user/tenant credentials with the Identity service and, upon success, create and return a token with the Token service. Identity -------- The Identity service provides auth credential validation and data about Users, Tenants and Roles, as well as any associated metadata. In the basic case all this data is managed by the service, allowing the service to manage all the CRUD associated with the data. In other cases, this data is pulled, by varying degrees, from an authoritative backend service. An example of this would be when backending on LDAP. See `LDAP Backend` below for more details. Token ----- The Token service validates and manages Tokens used for authenticating requests once a user/tenant's credentials have already been verified. Catalog ------- The Catalog service provides an endpoint registry used for endpoint discovery. Policy ------ The Policy service provides a rule-based authorization engine and the associated rule management interface. ------------------------ Application Construction ------------------------ Keystone is an HTTP front-end to several services. Like other OpenStack applications, this is done using python WSGI interfaces and applications are configured together using Paste_. The application's HTTP endpoints are made up of pipelines of WSGI middleware, such as:: [pipeline:public_api] pipeline = token_auth admin_token_auth json_body debug ec2_extension public_service These in turn use a subclass of :mod:`keystone.common.wsgi.ComposingRouter` to link URLs to Controllers (a subclass of :mod:`keystone.common.wsgi.Application`). Within each Controller, one or more Managers are loaded (for example, see :mod:`keystone.catalog.core.Manager`), which are thin wrapper classes which load the appropriate service driver based on the keystone configuration. * Identity * :mod:`keystone.identity.core.TenantController` * :mod:`keystone.identity.core.UserController` * :mod:`keystone.identity.core.RoleController` * Catalog * :mod:`keystone.catalog.core.ServiceController` * :mod:`keystone.service.VersionController` * Token * :mod:`keystone.service.TokenController` * Misc * :mod:`keystone.service.ExtensionsController` At this time, the policy service and associated manager is not exposed as a URL frontend, and has no associated Controller class. .. _Paste: http://pythonpaste.org/ ---------------- Service Backends ---------------- Each of the services can configured to use a backend to allow Keystone to fit a variety of environments and needs. The backend for each service is defined in the keystone.conf file with the key ``driver`` under a group associated with each service. A general class under each backend named ``Driver`` exists to provide an abstract base class for any implementations, identifying the expected service implementations. The drivers for the services are: * :mod:`keystone.identity.core.Driver` * :mod:`keystone.token.core.Driver` If you implement a backend driver for one of the keystone services, you're expected to subclass from these classes. The default response for the defined apis in these Drivers is to raise a :mod:`keystone.service.TokenController`. SQL Backend ----------- A SQL based backend using SQLAlchemy to store data persistently. The keystone-manage command introspects the backends to identify SQL based backends when running "db_sync" to establish or upgrade schema. If the backend driver has a method db_sync(), it will be invoked to sync and/or migrate schema. PAM Backend ----------- Extra simple backend that uses the current system's PAM service to authenticate, providing a one-to-one relationship between Users and Tenants with the `root` User also having the 'admin' role. Templated Backend ----------------- Largely designed for a common use case around service catalogs in the Keystone project, a Catalog backend that simply expands pre-configured templates to provide catalog data. Example paste.deploy config (uses $ instead of % to avoid ConfigParser's interpolation):: [DEFAULT] catalog.RegionOne.identity.publicURL = http://localhost:$(public_port)s/v2.0 catalog.RegionOne.identity.adminURL = http://localhost:$(public_port)s/v2.0 catalog.RegionOne.identity.internalURL = http://localhost:$(public_port)s/v2.0 catalog.RegionOne.identity.name = 'Identity Service' LDAP Backend ------------ The LDAP backend stored Users and Tenants in separate Subtrees. Roles are recorded as entries under the Tenants. ---------- Data Model ---------- Keystone was designed from the ground up to be amenable to multiple styles of backends and as such many of the methods and data types will happily accept more data than they know what to do with and pass them on to a backend. There are a few main data types: * **User**: has account credentials, is associated with one or more tenants * **Tenant**: unit of ownership in openstack, contains one or more users * **Role**: a first-class piece of metadata associated with many user-tenant pairs. * **Token**: identifying credential associated with a user or user and tenant * **Extras**: bucket of key-value metadata associated with a user-tenant pair. * **Rule**: describes a set of requirements for performing an action. While the general data model allows a many-to-many relationship between Users and Tenants and a many-to-one relationship between Extras and User-Tenant pairs, the actual backend implementations take varying levels of advantage of that functionality. ---------------- Approach to CRUD ---------------- While it is expected that any "real" deployment at a large company will manage their users, tenants and other metadata in their existing user systems, a variety of CRUD operations are provided for the sake of development and testing. CRUD is treated as an extension or additional feature to the core feature set in that it is not required that a backend support it. It is expected that backends for services that don't support the CRUD operations will raise a :mod:`keystone.exception.NotImplemented`. ---------------------------------- Approach to Authorization (Policy) ---------------------------------- Various components in the system require that different actions are allowed based on whether the user is authorized to perform that action. For the purposes of Keystone there are only a couple levels of authorization being checked for: * Require that the performing user is considered an admin. * Require that the performing user matches the user being referenced. Other systems wishing to use the policy engine will require additional styles of checks and will possibly write completely custom backends. Backends included in Keystone are: Rules ----- Given a list of matches to check for, simply verify that the credentials contain the matches. For example: .. code:: python credentials = {'user_id': 'foo', 'is_admin': 1, 'roles': ['nova:netadmin']} # An admin only call: policy_api.enforce(('is_admin:1',), credentials) # An admin or owner call: policy_api.enforce(('is_admin:1', 'user_id:foo'), credentials) # A netadmin call: policy_api.enforce(('roles:nova:netadmin',), credentials) Credentials are generally built from the user metadata in the 'extras' part of the Identity API. So, adding a 'role' to the user just means adding the role to the user metadata. Capability RBAC --------------- (Not yet implemented.) Another approach to authorization can be action-based, with a mapping of roles to which capabilities are allowed for that role. For example: .. code:: python credentials = {'user_id': 'foo', 'is_admin': 1, 'roles': ['nova:netadmin']} # add a policy policy_api.add_policy('action:nova:add_network', ('roles:nova:netadmin',)) policy_api.enforce(('action:nova:add_network',), credentials) In the backend this would look up the policy for 'action:nova:add_network' and then do what is effectively a 'Simple Match' style match against the creds. keystone-2014.1/doc/source/api_curl_examples.rst0000664000175400017540000002672512323716267023120 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. =============================== Service API Examples Using Curl =============================== The service API is defined to be a subset of the Admin API and, by default, runs on port 5000. GET / ===== This call is identical to that documented for the Admin API, except that it uses port 5000, instead of port 35357, by default:: $ curl http://0.0.0.0:5000 or:: $ curl http://0.0.0.0:5000/v2.0/ See the `Admin API Examples Using Curl`_ for more info. GET /extensions =============== This call is identical to that documented for the Admin API. POST /tokens ============ This call is identical to that documented for the Admin API. GET /tenants ============ List all of the tenants your token can access:: $ curl -H "X-Auth-Token:887665443383838" http://localhost:5000/v2.0/tenants Returns:: { "tenants_links": [], "tenants": [ { "enabled": true, "description": "None", "name": "customer-x", "id": "1" } ] } ============================= Admin API Examples Using Curl ============================= These examples assume a default port value of 35357, and depend on the ``sampledata`` bundled with keystone. GET / ===== Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types:: $ curl http://0.0.0.0:35357 or:: $ curl http://0.0.0.0:35357/v2.0/ Returns:: { "version":{ "id":"v2.0", "status":"beta", "updated":"2011-11-19T00:00:00Z", "links":[ { "rel":"self", "href":"http://127.0.0.1:35357/v2.0/" }, { "rel":"describedby", "type":"text/html", "href":"http://docs.openstack.org/api/openstack-identity-service/2.0/content/" }, { "rel":"describedby", "type":"application/pdf", "href":"http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf" }, { "rel":"describedby", "type":"application/vnd.sun.wadl+xml", "href":"http://127.0.0.1:35357/v2.0/identity-admin.wadl" } ], "media-types":[ { "base":"application/xml", "type":"application/vnd.openstack.identity-v2.0+xml" }, { "base":"application/json", "type":"application/vnd.openstack.identity-v2.0+json" } ] } } GET /extensions =============== Discover the API extensions enabled at the endpoint:: $ curl http://localhost:35357/v2.0/extensions/ Returns:: { "extensions":{ "values":[] } } POST /tokens ============ Authenticate by exchanging credentials for an access token:: $ curl -d '{"auth":{"tenantName": "customer-x", "passwordCredentials": {"username": "joeuser", "password": "secrete"}}}' -H "Content-type: application/json" http://localhost:35357/v2.0/tokens Returns:: { "access":{ "token":{ "expires":"2012-02-05T00:00:00", "id":"887665443383838", "tenant":{ "id":"1", "name":"customer-x" } }, "serviceCatalog":[ { "endpoints":[ { "adminURL":"http://swift.admin-nets.local:8080/", "region":"RegionOne", "internalURL":"http://127.0.0.1:8080/v1/AUTH_1", "publicURL":"http://swift.publicinternets.com/v1/AUTH_1" } ], "type":"object-store", "name":"swift" }, { "endpoints":[ { "adminURL":"http://cdn.admin-nets.local/v1.1/1", "region":"RegionOne", "internalURL":"http://127.0.0.1:7777/v1.1/1", "publicURL":"http://cdn.publicinternets.com/v1.1/1" } ], "type":"object-store", "name":"cdn" } ], "user":{ "id":"1", "roles":[ { "tenantId":"1", "id":"3", "name":"Member" } ], "name":"joeuser" } } } .. note:: Take note of the value ['access']['token']['id'] value produced here (``887665443383838``, above), as you can use it in the calls below. GET /tokens/{token_id} ====================== .. note:: This call refers to a token known to be valid, ``887665443383838`` in this case. Validate a token:: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/tokens/887665443383838 If the token is valid, returns:: { "access":{ "token":{ "expires":"2012-02-05T00:00:00", "id":"887665443383838", "tenant":{ "id":"1", "name":"customer-x" } }, "user":{ "name":"joeuser", "tenantName":"customer-x", "id":"1", "roles":[ { "serviceId":"1", "id":"3", "name":"Member" } ], "tenantId":"1" } } } HEAD /tokens/{token_id} ======================= This is a high-performance variant of the GET call documented above, which by definition, returns no response body:: $ curl -I -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/tokens/887665443383838 ... which returns ``200``, indicating the token is valid:: HTTP/1.1 200 OK Content-Length: 0 Content-Type: None Date: Tue, 08 Nov 2011 23:07:44 GMT GET /tokens/{token_id}/endpoints ================================ List all endpoints for a token:: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/tokens/887665443383838/endpoints Returns:: { "endpoints_links": [ { "href": "http://127.0.0.1:35357/tokens/887665443383838/endpoints?'marker=5&limit=10'", "rel": "next" } ], "endpoints": [ { "internalURL": "http://127.0.0.1:8080/v1/AUTH_1", "name": "swift", "adminURL": "http://swift.admin-nets.local:8080/", "region": "RegionOne", "tenantId": 1, "type": "object-store", "id": 1, "publicURL": "http://swift.publicinternets.com/v1/AUTH_1" }, { "internalURL": "http://localhost:8774/v1.0", "name": "nova_compat", "adminURL": "http://127.0.0.1:8774/v1.0", "region": "RegionOne", "tenantId": 1, "type": "compute", "id": 2, "publicURL": "http://nova.publicinternets.com/v1.0/" }, { "internalURL": "http://localhost:8774/v1.1", "name": "nova", "adminURL": "http://127.0.0.1:8774/v1.1", "region": "RegionOne", "tenantId": 1, "type": "compute", "id": 3, "publicURL": "http://nova.publicinternets.com/v1.1/ }, { "internalURL": "http://127.0.0.1:9292/v1.1/", "name": "glance", "adminURL": "http://nova.admin-nets.local/v1.1/", "region": "RegionOne", "tenantId": 1, "type": "image", "id": 4, "publicURL": "http://glance.publicinternets.com/v1.1/" }, { "internalURL": "http://127.0.0.1:7777/v1.1/1", "name": "cdn", "adminURL": "http://cdn.admin-nets.local/v1.1/1", "region": "RegionOne", "tenantId": 1, "type": "object-store", "id": 5, "publicURL": "http://cdn.publicinternets.com/v1.1/1" } ] } GET /tenants ============ List all of the tenants in the system (requires an Admin ``X-Auth-Token``):: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/tenants Returns:: { "tenants_links": [], "tenants": [ { "enabled": false, "description": "None", "name": "project-y", "id": "3" }, { "enabled": true, "description": "None", "name": "ANOTHER:TENANT", "id": "2" }, { "enabled": true, "description": "None", "name": "customer-x", "id": "1" } ] } GET /tenants/{tenant_id} ======================== Retrieve information about a tenant, by tenant ID:: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/tenants/1 Returns:: { "tenant":{ "enabled":true, "description":"None", "name":"customer-x", "id":"1" } } GET /tenants/{tenant_id}/users/{user_id}/roles ============================================== List the roles a user has been granted on a tenant:: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/tenants/1/users/1/roles Returns:: { "roles_links":[], "roles":[ { "id":"3", "name":"Member" } ] } GET /users/{user_id} ==================== Retrieve information about a user, by user ID:: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/users/1 Returns:: { "user":{ "tenantId":"1", "enabled":true, "id":"1", "name":"joeuser" } } GET /users/{user_id}/roles ========================== Retrieve the roles granted to a user, given a user ID:: $ curl -H "X-Auth-Token:999888777666" http://localhost:35357/v2.0/users/4/roles Returns:: { "roles_links":[], "roles":[ { "id":"2", "name":"KeystoneServiceAdmin" } ] } keystone-2014.1/doc/source/developing.rst0000664000175400017540000006536712323716272021561 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ======================== Developing with Keystone ======================== Setup ----- Get your development environment set up according to :doc:`setup`. The instructions from here will assume that you have installed keystone into a virtualenv. If you chose not to, simply exclude "tools/with_venv.sh" from the example commands below. Configuring Keystone -------------------- keystone requires a configuration file. There is a sample configuration file that can be used to get started:: $ cp etc/keystone.conf.sample etc/keystone.conf The defaults are enough to get you going, but you can make any changes if needed. Running Keystone ---------------- To run the keystone Admin and API server instances, use:: $ tools/with_venv.sh bin/keystone-all this runs keystone with the configuration the etc/ directory of the project. See :doc:`configuration` for details on how Keystone is configured. By default, keystone is configured with SQL backends. Interacting with Keystone ------------------------- You can interact with Keystone through the command line using :doc:`man/keystone-manage` which allows you to initialize keystone, etc. You can also interact with Keystone through its REST API. There is a python keystone client library `python-keystoneclient`_ which interacts exclusively through the REST API, and which keystone itself uses to provide its command-line interface. When initially getting set up, after you've configured which databases to use, you're probably going to need to run the following to your database schema in place:: $ bin/keystone-manage db_sync .. _`python-keystoneclient`: https://github.com/openstack/python-keystoneclient Database Schema Migrations -------------------------- Keystone uses SQLAlchemy-migrate_ to migrate the SQL database between revisions. For core components, the migrations are kept in a central repository under ``keystone/common/sql/migrate_repo``. .. _SQLAlchemy-migrate: http://code.google.com/p/sqlalchemy-migrate/ Extensions should be created as directories under ``keystone/contrib``. An extension that requires SQL migrations should not change the common repository, but should instead have its own repository. This repository must be in the extension's directory in ``keystone/contrib//migrate_repo``. In addition, it needs a subdirectory named ``versions``. For example, if the extension name is ``my_extension`` then the directory structure would be ``keystone/contrib/my_extension/migrate_repo/versions/``. For the migration to work, both the ``migrate_repo`` and ``versions`` subdirectories must have ``__init__.py`` files. SQLAlchemy-migrate will look for a configuration file in the ``migrate_repo`` named ``migrate.cfg``. This conforms to a key/value `ini` file format. A sample configuration file with the minimal set of values is:: [db_settings] repository_id=my_extension version_table=migrate_version required_dbs=[] The directory ``keystone/contrib/example`` contains a sample extension migration. Migrations must be explicitly run for each extension individually. To run a migration for a specific extension, simply run:: $ keystone-manage db_sync --extension Initial Sample Data ------------------- There is an included script which is helpful in setting up some initial sample data for use with keystone:: $ OS_SERVICE_TOKEN=ADMIN tools/with_venv.sh tools/sample_data.sh Notice it requires a service token read from an environment variable for authentication. The default value "ADMIN" is from the ``admin_token`` option in the ``[DEFAULT]`` section in ``etc/keystone.conf``. Once run, you can see the sample data that has been created by using the `python-keystoneclient`_ command-line interface:: $ tools/with_venv.sh keystone --os-token ADMIN --os-endpoint http://127.0.0.1:35357/v2.0/ user-list Filtering responsibilities between controllers and drivers ---------------------------------------------------------- Keystone supports the specification of filtering on list queries as part of the v3 identity API. By default these queries are satisfied in the controller class when a controller calls the ``wrap_collection`` method at the end of a ``list_{entity}`` method. However, to enable optimum performance, any driver can implement some or all of the specified filters (for example, by adding filtering to the generated SQL statements to generate the list). The communication of the filter details between the controller level and its drivers is handled by the passing of a reference to a Hints object, which is a list of dicts describing the filters. A driver that satisfies a filter must delete the filter from the Hints object so that when it is returned back to the controller level, it knows to only execute any unsatisfied filters. The contract for a driver for ``list_{entity}`` methods is therefore: * It MUST return a list of entities of the specified type * It MAY either just return all such entities, or alternatively reduce the list by filtering for one or more of the specified filters in the passed Hints reference, and removing any such satisfied filters. Entity list truncation by drivers --------------------------------- Keystone supports the ability for a deployment to restrict the number of entries returned from ``list_{entity}`` methods, typically to prevent poorly formed searches (e.g. without sufficient filters) from becoming a performance issue. These limits are set in the configuration file, either for a specific driver or across all drivers. These limits are read at the Manager level and passed into individual drivers as part of the Hints list object. A driver should try and honor any such limit if possible, but if it is unable to do so then it may ignore it (and the truncation of the returned list of entities will happen at the controller level). Testing ------- Running Tests ============= Before running tests, you should have ``tox`` installed and available in your environment (in addition to the other external dependencies in :doc:`setup`):: $ pip install tox .. NOTE:: You may need to perform both the above operation and the next inside a python virtualenv, or prefix the above command with ``sudo``, depending on your preference. To execute the full suite of tests maintained within Keystone, simply run:: $ tox This iterates over multiple configuration variations, and uses external projects to do light integration testing to verify the Identity API against other projects. .. NOTE:: The first time you run ``tox``, it will take additional time to build virtualenvs. You can later use the ``-r`` option with ``tox`` to rebuild your virtualenv in a similar manner. To run tests for one or more specific test environments (for example, the most common configuration of Python 2.7 and PEP-8), list the environments with the ``-e`` option, separated by spaces:: $ tox -e py27,pep8 See ``tox.ini`` for the full list of available test environments. Running with PDB ~~~~~~~~~~~~~~~~ Using PDB breakpoints with tox and testr normally doesn't work since the tests just fail with a BdbQuit exception rather than stopping at the breakpoint. To run with PDB breakpoints during testing, use the ``debug`` tox environment rather than ``py27``. Here's an example, passing the name of a test since you'll normally only want to run the test that hits your breakpoint:: $ tox -e debug keystone.tests.test_auth.AuthWithToken.test_belongs_to For reference, the ``debug`` tox environment implements the instructions here: https://wiki.openstack.org/wiki/Testr#Debugging_.28pdb.29_Tests Test Structure ============== Not all of the tests in the tests directory are strictly unit tests. Keystone intentionally includes tests that run the service locally and drives the entire configuration to achieve basic functional testing. For the functional tests, an in-memory key-value store is used to keep the tests fast. Within the tests directory, the general structure of the tests is a basic set of tests represented under a test class, and then subclasses of those tests under other classes with different configurations to drive different backends through the APIs. For example, ``test_backend.py`` has a sequence of tests under the class ``IdentityTests`` that will work with the default drivers as configured in this projects etc/ directory. ``test_backend_sql.py`` subclasses those tests, changing the configuration by overriding with configuration files stored in the tests directory aimed at enabling the SQL backend for the Identity module. Likewise, ``test_keystoneclient.py`` takes advantage of the tests written against ``KeystoneClientTests`` to verify the same tests function through different drivers and releases of the Keystone client. The class ``CompatTestCase`` does the work of checking out a specific version of python-keystoneclient, and then verifying it against a temporarily running local instance to explicitly verify basic functional testing across the API. Testing Schema Migrations ========================= The application of schema migrations can be tested using SQLAlchemy Migrate’s built-in test runner, one migration at a time. .. WARNING:: This may leave your database in an inconsistent state; attempt this in non-production environments only! This is useful for testing the *next* migration in sequence (both forward & backward) in a database under version control:: python keystone/common/sql/migrate_repo/manage.py test \ --url=sqlite:///test.db \ --repository=keystone/common/sql/migrate_repo/ This command references to a SQLite database (test.db) to be used. Depending on the migration, this command alone does not make assertions as to the integrity of your data during migration. Writing Tests ============= To add tests covering all drivers, update the relevant base test class (``test_backend.py``, ``test_legacy_compat.py``, and ``test_keystoneclient.py``). To add new drivers, subclass the ``test_backend.py`` (look towards ``test_backend_sql.py`` or ``test_backend_kvs.py`` for examples) and update the configuration of the test class in ``setUp()``. Further Testing =============== devstack_ is the *best* way to quickly deploy keystone with the rest of the OpenStack universe and should be critical step in your development workflow! You may also be interested in either the `OpenStack Continuous Integration Infrastructure`_ or the `OpenStack Integration Testing Project`_. .. _devstack: http://devstack.org/ .. _OpenStack Continuous Integration Infrastructure: http://ci.openstack.org .. _OpenStack Integration Testing Project: https://github.com/openstack/tempest LDAP Tests ========== LDAP has a fake backend that performs rudimentary operations. If you are building more significant LDAP functionality, you should test against a live LDAP server. Devstack has an option to set up a directory server for Keystone to use. Add ldap to the ``ENABLED_SERVICES`` environment variable, and set environment variables ``KEYSTONE_IDENTITY_BACKEND=ldap`` and ``KEYSTONE_CLEAR_LDAP=yes`` in your ``localrc`` file. The unit tests can be run against a live server with ``keystone/tests/test_ldap_livetest.py``. The default password is ``test`` but if you have installed devstack with a different LDAP password, modify the file ``keystone/tests/backend_liveldap.conf`` to reflect your password. .. NOTE:: To run the live tests you need to set the environment variable ``ENABLE_LDAP_LIVE_TEST`` to a non-negative value. Generating Updated Sample Config File ------------------------------------- Keystone's sample configuration file ``etc/keystone.conf.sample`` is automatically generated based upon all of the options available within Keystone. These options are sourced from the many files around Keystone as well as some external libraries. If new options are added, primarily located in ``keystone.common.config``, a new sample configuration file needs to be generated. Generating a new sample configuration to be included in a commit run:: $ tox -esample_config -r The tox command will place an updated sample config in ``etc/keystone.conf.sample``. If there is a new external library (e.g. ``oslo.messaging``) that utilizes the ``oslo.config`` package for configuration, it can be added to the list of libraries found in ``tools/config/oslo.config.generator.rc``. Translated responses -------------------- The Keystone server can provide error responses translated into the language in the ``Accept-Language`` header of the request. In order to test this in your development environment, there's a couple of things you need to do. 1. Build the message files. Run the following command in your keystone directory:: $ python setup.py compile_catalog This will generate .mo files like keystone/locale/[lang]/LC_MESSAGES/[lang].mo 2. When running Keystone, set the ``KEYSTONE_LOCALEDIR`` environment variable to the keystone/locale directory. For example:: $ KEYSTONE_LOCALEDIR=/opt/stack/keystone/keystone/locale keystone-all Now you can get a translated error response:: $ curl -s -H "Accept-Language: zh" http://localhost:5000/notapath | python -mjson.tool { "error": { "code": 404, "message": "\u627e\u4e0d\u5230\u8cc7\u6e90\u3002", "title": "Not Found" } } Caching Layer ------------- The caching layer is designed to be applied to any ``manager`` object within Keystone via the use of the ``on_arguments`` decorator provided in the ``keystone.common.cache`` module. This decorator leverages `dogpile.cache`_ caching system to provide a flexible caching backend. It is recommended that each of the managers have an independent toggle within the config file to enable caching. The easiest method to utilize the toggle within the configuration file is to define a ``caching`` boolean option within that manager's configuration section (e.g. ``identity``). Once that option is defined you can pass function to the ``on_arguments`` decorator with the named argument ``should_cache_fn``. In the ``keystone.common.cache`` module, there is a function called ``should_cache_fn``, which will provide a reference, to a function, that will consult the global cache ``enabled`` option as well as the specific manager's caching enable toggle. .. NOTE:: If a section-specific boolean option is not defined in the config section specified when calling ``should_cache_fn``, the returned function reference will default to enabling caching for that ``manager``. Example use of cache and ``should_cache_fn`` (in this example, ``token`` is the manager): .. code:: python from keystone.common import cache SHOULD_CACHE = cache.should_cache_fn('token') @cache.on_arguments(should_cache_fn=SHOULD_CACHE) def cacheable_function(arg1, arg2, arg3): ... return some_value With the above example, each call to the ``cacheable_function`` would check to see if the arguments passed to it matched a currently valid cached item. If the return value was cached, the caching layer would return the cached value; if the return value was not cached, the caching layer would call the function, pass the value to the ``SHOULD_CACHE`` function reference, which would then determine if caching was globally enabled and enabled for the ``token`` manager. If either caching toggle is disabled, the value is returned but not cached. It is recommended that each of the managers have an independent configurable time-to-live (TTL). If a configurable TTL has been defined for the manager configuration section, it is possible to pass it to the ``cache.on_arguments`` decorator with the named-argument ``expiration_time``. For consistency, it is recommended that this option be called ``cache_time`` and default to ``None``. If the ``expiration_time`` argument passed to the decorator is set to ``None``, the expiration time will be set to the global default (``expiration_time`` option in the ``[cache]`` configuration section. Example of using a section specific ``cache_time`` (in this example, ``identity`` is the manager): .. code:: python from keystone.common import cache SHOULD_CACHE = cache.should_cache_fn('identity') @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=CONF.identity.cache_time) def cachable_function(arg1, arg2, arg3): ... return some_value For cache invalidation, the ``on_arguments`` decorator will add an ``invalidate`` method (attribute) to your decorated function. To invalidate the cache, you pass the same arguments to the ``invalidate`` method as you would the normal function. Example (using the above cacheable_function): .. code:: python def invalidate_cache(arg1, arg2, arg3): cacheable_function.invalidate(arg1, arg2, arg3) .. WARNING:: The ``on_arguments`` decorator does not accept keyword-arguments/named arguments. An exception will be raised if keyword arguments are passed to a caching-decorated function. .. NOTE:: In all cases methods work the same as functions except if you are attempting to invalidate the cache on a decorated bound-method, you need to pass ``self`` to the ``invalidate`` method as the first argument before the arguments. .. _`dogpile.cache`: http://dogpilecache.readthedocs.org/ dogpile.cache based Key-Value-Store (KVS) ----------------------------------------- The ``dogpile.cache`` based KVS system has been designed to allow for flexible stores for the backend of the KVS system. The implementation allows for the use of any normal ``dogpile.cache`` cache backends to be used as a store. All interfacing to the KVS system happens via the ``KeyValueStore`` object located at ``keystone.common.kvs.KeyValueStore``. To utilize the KVS system an instantiation of the ``KeyValueStore`` class is needed. To accquire a KeyValueStore instantiation use the ``keystone.common.kvs.get_key_value_store`` factory function. This factory will either create a new ``KeyValueStore`` object or retrieve the already instantiated ``KeyValueStore`` object by the name passed as an argument. The object must be configured before use. The KVS object will only be retrievable with the ``get_key_value_store`` function while there is an active reference outside of the registry. Once all references have been removed the object is gone (the registry uses a ``weakref`` to match the object to the name). Example Instantiation and Configuration: .. code:: python kvs_store = kvs.get_key_value_store('TestKVSRegion') kvs_store.configure('openstack.kvs.Memory', ...) Any keyword arguments passed to the configure method that are not defined as part of the KeyValueStore object configuration are passed to the backend for further configuration (e.g. memcached servers, lock_timeout, etc). The memcached backend uses the Keystone manager mechanism to support the use of any of the provided memcached backends (``bmemcached``, ``pylibmc``, and basic ``memcached``). By default the ``memcached`` backend is used. Currently the Memcache URLs come from the ``servers`` option in the ``[memcache]`` configuration section of the Keystone config. The following is an example showing how to configure the KVS system to use a KeyValueStore object named "TestKVSRegion" and a specific Memcached driver: .. code:: python kvs_store = kvs.get_key_value_store('TestKVSRegion') kvs_store.configure('openstack.kvs.Memcached', memcached_backend='Memcached') The memcached backend supports a mechanism to supply an explicit TTL (in seconds) to all keys set via the KVS object. This is accomplished by passing the argument ``memcached_expire_time`` as a keyword argument to the ``configure`` method. Passing the ``memcache_expire_time`` argument will cause the ``time`` argument to be added to all ``set`` and ``set_multi`` calls performed by the memcached client. ``memcached_expire_time`` is an argument exclusive to the memcached dogpile backend, and will be ignored if passed to another backend: .. code:: python kvs_store.configure('openstack.kvs.Memcached', memcached_backend='Memcached', memcached_expire_time=86400) If an explicit TTL is configured via the ``memcached_expire_time`` argument, it is possible to exempt specific keys from receiving the TTL by passing the argument ``no_expiry_keys`` (list) as a keyword argument to the ``configure`` method. ``no_expiry_keys`` should be supported by all OpenStack-specific dogpile backends (memcached) that have the ability to set an explicit TTL: .. code:: python kvs_store.configure('openstack.kvs.Memcached', memcached_backend='Memcached', memcached_expire_time=86400, no_expiry_keys=['key', 'second_key', ...]) .. NOTE:: For the non-expiring keys functionality to work, the backend must support the ability for the region to set the key_mangler on it and have the attribute ``raw_no_expiry_keys``. In most cases, support for setting the key_mangler on the backend is handled by allowing the region object to set the ``key_mangler`` attribute on the backend. The ``raw_no_expiry_keys`` attribute is expected to be used to hold the values of the keyword argument ``no_expiry_keys`` prior to hashing. It is the responsibility of the backend to use these raw values to determine if a key should be exempt from expiring and not set the TTL on the non-expiring keys when the ``set`` or ``set_multi`` methods are called. Typically the key will be hashed by the region using its key_mangler method before being passed to the backend to set the value in the KeyValueStore. This means that in most cases, the backend will need to either pre-compute the hashed versions of the keys (when the key_mangler is set) and store a cached copy, or hash each item in the ``raw_no_expiry_keys`` attribute on each call to ``.set()`` and ``.set_multi()``. The ``memcached`` backend handles this hashing and caching of the keys by utilizing an ``@property`` method for the ``.key_mangler`` attribute on the backend and utilizing the associated ``.settr()`` method to front-load the hashing work at attribute set time. Once a KVS object has been instantiated the method of interacting is the same as most memcache implementations: .. code:: python kvs_store = kvs.get_key_value_store('TestKVSRegion') kvs_store.configure(...) # Set a Value kvs_store.set(, ) # Retrieve a value: retrieved_value = kvs_store.get() # Delete a key/value pair: kvs_store.delete() # multi-get: kvs_store.get_multi([, , ...]) # multi-set: kvs_store.set_multi(dict(=, =, ...)) # multi-delete kvs_store.delete_multi([, , ...]) There is a global configuration option to be aware of (that can be set in the ``[kvs]`` section of the Keystone configuration file): ``enable_key_mangler`` can be set top false, disabling the use of key_manglers (modification of the key when saving to the backend to help prevent collisions or exceeding key size limits with memcached). .. NOTE:: The ``enable_key_mangler`` option in the ``[kvs]`` section of the Keystone configuration file is not the same option (and does not affect the cache-layer key manglers) from the option in the ``[cache]`` section of the configuration file. Similarly the ``[cache]`` section options relating to key manglers has no bearing on the ``[kvs]`` objects. .. WARNING:: Setting the ``enable_key_mangler`` option to False can have detrimental effects on the KeyValueStore backend. It is recommended that this value is not set to False except for debugging issues with the ``dogpile.cache`` backend itself. Any backends that are to be used with the ``KeyValueStore`` system need to be registered with dogpile. For in-tree/provided backends, the registration should occur in ``keystone/common/kvs/__init__.py``. For backends that are developed out of tree, the location should be added to the ``backends`` option in the ``[kvs]`` section of the Keystone configuration:: [kvs] backends = backend_module1.backend_class1,backend_module2.backend_class2 All registered backends will receive the "short name" of "openstack.kvs." for use in the ``configure`` method on the ``KeyValueStore`` object. The ```` of a backend must be globally unique. dogpile.cache based MongoDB (NoSQL) backend -------------------------------------------- The ``dogpile.cache`` based MongoDB backend implementation allows for various MongoDB configurations, e.g., standalone, a replica set, sharded replicas, with or without SSL, use of TTL type collections, etc. Example of typical configuration for MongoDB backend: .. code:: python from dogpile.cache import region arguments = { 'db_hosts': 'localhost:27017', 'db_name': 'ks_cache', 'cache_collection': 'cache', 'username': 'test_user', 'password': 'test_password', # optional arguments 'son_manipulator': 'my_son_manipulator_impl' } region.make_region().configure('keystone.cache.mongo', arguments=arguments) The optional `son_manipulator` is used to manipulate custom data type while its saved in or retrieved from MongoDB. If the dogpile cached values contain built-in data types and no custom classes, then the provided implementation class is sufficient. For further details, refer http://api.mongodb.org/python/current/examples/custom_type.html#automatic-encoding-and-decoding Similar to other backends, this backend can be added via keystone configuration in ``keystone.conf``:: [cache] # Global cache functionality toggle. enabled = True # Referring to specific cache backend backend = keystone.cache.mongo # Backend specific configuration arguments backend_argument = db_hosts:localhost:27017 backend_argument = db_name:ks_cache backend_argument = cache_collection:cache backend_argument = username:test_user backend_argument = password:test_password This backend is registered in ``keystone.common.cache.core`` module. So, its usage is similar to other dogpile caching backends as it implements the same dogpile APIs. Building the Documentation -------------------------- The documentation is generated with Sphinx uning the tox command. To create HTML docs and man pages:: $ tox -e docs The results are in the docs/build/html and docs/build/man directories respectively. keystone-2014.1/doc/source/static/0000775000175400017540000000000012323716511020135 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/source/static/basic.css0000664000175400017540000001462512323716267021750 0ustar jenkinsjenkins00000000000000/** * Sphinx stylesheet -- basic theme * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* -- main layout ----------------------------------------------------------- */ div.clearer { clear: both; } /* -- relbar ---------------------------------------------------------------- */ div.related { width: 100%; font-size: 90%; } div.related h3 { display: none; } div.related ul { margin: 0; padding: 0 0 0 10px; list-style: none; } div.related li { display: inline; } div.related li.right { float: right; margin-right: 5px; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; } div.sphinxsidebar { float: left; width: 230px; margin-left: -100%; font-size: 90%; } div.sphinxsidebar ul { list-style: none; } div.sphinxsidebar ul ul, div.sphinxsidebar ul.want-points { margin-left: 20px; list-style: square; } div.sphinxsidebar ul ul { margin-top: 0; margin-bottom: 0; } div.sphinxsidebar form { margin-top: 10px; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } img { border: 0; } /* -- search page ----------------------------------------------------------- */ ul.search { margin: 10px 0 0 20px; padding: 0; } ul.search li { padding: 5px 0 5px 20px; background-image: url(file.png); background-repeat: no-repeat; background-position: 0 7px; } ul.search li a { font-weight: bold; } ul.search li div.context { color: #888; margin: 2px 0 0 30px; text-align: left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- index page ------------------------------------------------------------ */ table.contentstable { width: 90%; } table.contentstable p.biglink { line-height: 150%; } a.biglink { font-size: 1.3em; } span.linkdescr { font-style: italic; padding-top: 5px; font-size: 90%; } /* -- general index --------------------------------------------------------- */ table.indextable td { text-align: left; vertical-align: top; } table.indextable dl, table.indextable dd { margin-top: 0; margin-bottom: 0; } table.indextable tr.pcap { height: 10px; } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2; } img.toggler { margin-right: 3px; margin-top: 3px; cursor: pointer; } /* -- general body styles --------------------------------------------------- */ a.headerlink { visibility: hidden; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .field-list ul { padding-left: 1em; } .first { } p.rubric { margin-top: 30px; font-weight: bold; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px 7px 0 7px; background-color: #ffe; width: 40%; float: right; } p.sidebar-title { font-weight: bold; } /* -- topics ---------------------------------------------------------------- */ div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- admonitions ----------------------------------------------------------- */ div.admonition { margin-top: 10px; margin-bottom: 10px; padding: 7px; } div.admonition dt { font-weight: bold; } div.admonition dl { margin-bottom: 0; } p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; } div.body p.centered { text-align: center; margin-top: 25px; } /* -- tables ---------------------------------------------------------------- */ table.docutils { border: 0; border-collapse: collapse; } table.docutils td, table.docutils th { padding: 1px 8px 1px 0; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } table.field-list td, table.field-list th { border: 0 !important; } table.footnote td, table.footnote th { border: 0 !important; } th { text-align: left; padding-right: 5px; } /* -- other body styles ----------------------------------------------------- */ dl { margin-bottom: 15px; } dd p { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } dt:target, .highlight { background-color: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .refcount { color: #060; } .optional { font-size: 1.3em; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; } td.linenos pre { padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { margin-left: 0.5em; } table.highlighttable td { padding: 0 0.5em 0 0.5em; } tt.descname { background-color: transparent; font-weight: bold; font-size: 1.2em; } tt.descclassname { background-color: transparent; } tt.xref, a tt { background-color: transparent; font-weight: bold; } h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { background-color: transparent; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } /* -- printout stylesheet --------------------------------------------------- */ @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } } keystone-2014.1/doc/source/static/openstack_logo.png0000664000175400017540000000712612323716267023670 0ustar jenkinsjenkins00000000000000‰PNG  IHDR§8˜&èztEXtSoftwareAdobe ImageReadyqÉe< øIDATxÚìOP×Çß®VB ‹Á8c–¤cÒÄÅÄžtÚ¤ˆ:=¤ É%G‹c;“1\zèè¥ö`39tz2LO½4v;íøÐyòo:q‚ìq¦qÒ96c0âø+iûû­~O<–•´RfÌÎ>½}ÿvßg¿¿÷Þ®„¤ë:s̱J4Ù¹ŽUªIûÝ€Î=>òp=l «B˜Íol²éµµ¾Ÿ5?êtŸg¡°i°Óè£>C 1‚M-¶ŽGìÁÚzß/@8ÑÂg;´”Î4,åU·oÃ@8 ûG =Tí’/ãÔÉ%á&UDã@ŸlsÙIôZc͸"É^·,±ŸIU >EEîíö»ïþýñZÄéÎC¦œ¿×üÁjEo¬ªbªÛü.™à,Ÿ‚ʲ‹yª¼FXQÜÌ­x2aÅí6Â×H'X_ëŸÿæ(èdJ¾:ü­&¶2ŸU–4¥§ÚԀɕ†©ÚëËÄ{«k¶ôx÷r.—§Þúi:ÝzHàä– PY–Y]­ß®º•ÛpeÀó°Á)ª íÇZ™ª6:Wѱý‡“Špž<Úâ€éXY­¨Ç—k¨ZWï\=ÇvÙÄ™–!ØtÜöN´†šZ§'«<åṯJsÆö¡]‘‡K1ãqèÂê ÛJ&˜ fýϵ´9=Vœ« Â.ÐuóÁ¥' Î_F—#¿Óêú xyõ à!|“ÂQ¶½ô×(¡Î]c––úg8Q8˜ï®¶0lOœ *Øy‚ª7‰¶’^ŒÍDb; jº_1‰­ØÉ#GG˜³ÆieêAm¸bóä‚…\j0Ñ>þú ßXÏÖÆvPù‚á|ûí·5:?,#üÎ;ïD²¤Á- Ç£BFy¢6ëÈšÒÇáX˜>£Ú¡0D îJeÔHöƒë ñš§JîÝð^."” º4òpXN,"s.”'y¢yÒó7×¢˜öÆ!wÃv—ÊÐΞ={ âû± jB„`úÜÖ ®·p󧛎ÛË­Zè“WÁÁ¼»I²`x⬆/xÇa„ã!!n“—­ŽË6ÓcùãpL…mÂèŽqŸ1Þ¢Ãyû/RÚqˆ»lj3"Àë ô0°aþ jÛ Õ; ñ¡\ËE8ÛÛ…<—»Ÿê~—ÏcÄQöC×Miq¯*Å‚6»Ûñ™+Ãù[÷zÊ'Bø|ã±’”=D >@ÑØi!8µ°È¤NÓ"eº y¢\õL`†(í02Hé#V*M ¨4>䪠¶õ €ô›Ú¥á×uÞ´?϶ëŽ c}†êå`•ù*¥»Àëƒca³ü!¡¬¯]¨7›ºÒÇá,ªŒiÆHMkU4œÿüOÖ7Ô‚0N½.v R˜TˆßéÉ(Å3R~X¸_Ür¥&åâå…Mn:Dðô@Ü_øvŠ¿ Âfª£‹ƒ éù„¦×”þ˜¶YfˆÊŒӾà g Di²A/æ½X¦s¸DªiL²hlùF¾% €4ÎÎw¾A“ë·c ÙlγõòÛ(Í>­¶¢Ç‹aÐñAZJR S–›Â·T,L9nÖÕUÊ©•¨SCOœcæ%¦N^ @iYé¢Õ’S»HÈyÖ^"&õäKI}…d–+Î1V¾—NøÀÜê¥ÔúB\‘iq<œc¢U6£å™aA¥ìªg¯y"‡…MCbÚ¥•ÎØ>)Î8+ßsáhŽqe ×y[<© ˜¯-ÅÊ8›Î6µ=^e2›Ã‹h1ãqZrŠšfî¥ßJ*TŽ€ñ埠…ƒæ%¢,jïgFMë“W²¤/—z–RD4‹ò£‚G,°¼‘bÔ3/œ¦·’Ênœ{Z½ÖÕÞ_ëöä—ô56»76R»Œ+Âùô ñý‚f{ÙâšÅ{…aˆU‡hô¨´¤fîdáYxŒ¿üabEwOib¦Œ+ª–2Mx†Ïó©yæ±BÁ¶œhi‘tIøÛIopñV’ 8Í´ÌÂO¤Ûj©¢Æåb'}>v˜[ÞÚÌ$˜\\0¶¸'˜j÷­$t»Ì-¡ Ò#E&LÀúLOu̪‚/oD„6GLnëˆÐãÍAªãuRãzʇ¥½¼¹5AÏűÌv¡í#^‚ßtøB¶u€ÄGé*¿)Ct“[©ç(-Y…(O/»Fõ^ʦêv„®æ¶³•ódë ‰é:éÒ™î¡crL—k¥T1@N;1Â_ñ+ k3Z­ªLY^b'¼uˆk”ô)T»\¡/Ž{ö£;a›€ŽÒâù Ð±xÁr½¢FË7ã˜ÆŒÌ7„/‘°í—)¥Ç“jFMeâçó³kTHH‰ äÃfèe?Û~`„€{7 h}ç.“8 Ê7?¸$¨&®¼‘ï<%Ý»àTN/ÀéѬ†°çÇU›ßNÞúîF6gjU5{´–~áw3™7»Î|Š‹µUW³D*¹g×…?Ú°œH°oâqÐ`×Yæ8+K]8M“œW»,LJø……4ÅiœµYŸÑvò2cVí¦åÇLÃ;õ„¥¨’û$C1LÆê΂³àÄ߆ñ¾ìMýèE¶ZИ©Ñïgß­¯g©õõ’úâéʧ °vÁéXùMÜ9«B ™ŽñºK–e7«ò6°Õ]ÛjjÒnUp­èŠÝ²Ì\õ*{¼•Ø3œ._sc™nøN';’Ød §ÏœßLÝ×A=±Ï×`«Ò™¡˜«¤ÓÞ*ãI€³Ñ“cF­ìžkI§øÒãEÙëenou:¬¸™‹†.H#'Óa ¿’A_ËHÍN³DÂAó0*gŠàÄ_Ýr”pëU,•ÒAý– ýqîäbŒÕkϰ¤?ý°Å ð±$µ3ŠÓºÔã9kW^æ“^X‰O°"‰ù׿ù­óïGJc‘†Z_W^8I=Q®â´öé6TT×S,•XgÅüP\ô™l©Ê»0‡ÊïƒÌ"< ;”7œ~Ï£ÆcMÎ0%–tþW‘cû`;žÝ›žB ·Ò`²9˜-ÍTÕ­Ü®RÿužgËñíÉà\liWš­-Ëx‡ù1åŠqV†éÌåZÕ…qXžX&ÖÉãxz<ÆÏEl“¹<ÌcuÌñVõ–N´û¦9 ¸n5“J&§oyÔ÷oy|œÔS•Ì’ø«"{2ì¼k|B°= ûð³Û»Ò}øÙçÆþ½﬚§½3yŸÍ/,튿öþ'–P£Ý¸ý%túÜŽ#[]Xö“÷,à^ÜÏóa›¢÷gv–}õ½vÔk¤™¸mȯI®zË 'ÚÔÌt3™LÎonn~Ç?½)û®Ýt×'R èÀ³Ý)ÉBð­/'ÙÙÓìxs#kRý9Ó;}Šu´>•é\;†å¾úR€ÝºóuÕ\dm™róÕå÷ÕeVÑ/J×Áç&µÞˆçíÇc›¤pÚyL+*ä98o³Jz /Ö»±¹S!Íõ–k¶¾[ÊÎè-ÍÇà<¶¦t]ÖS)WÄ['ë&ŸÙ\ìÞÙÛ~ìwݤ–Q3ZªŠæÙ»ž·•Žw.vÔr|mGgç²:#½5Ìxcü¬ç¥® \¹êZ"7ÞØàÏ Š¹NTí›}n TD¼9¸!Ôw ®©açë¯S î „·³ã„íó. œhfêO57¯'¶¶èÆsw¦D¼µŠîÖå7=žWJ膬»B˜ƒ)•$C òò9ÃþìÕ”L™PMÑ¥cù"ºfíĶ:σb3Öf9îDµ5·£µ¹ n¤Se»y¿¦13;«;z”e²ÎôÔM¯?þ—u¶ø¦—½&¦]L¦îJŒ=öHÒ†,±OÝ’4GK¤a$ÀVñÿ//:vº¬œ JÂÓ¡Šdë(g7\“S3¬CÃJå:Z[ €ŒáEŽº¸{µ3œÀñ#‚°Ýº3™)Õ“Tïpùÿ©§wŒ9¿ ³õ¢‡éÍMMè}Ibq·Ûýß?­º¯ÿqnõW+++ëÉD’áëuð·ûpA?±_9Süïuv“ƒØñ8YI»ÞSÆ–ž¼¤Ý¡ð'>7Æiæq+æA8²ÁŒ.Ý6Š×—­.»†eñáª(B(Ž7±\Lƒ7 ~îì¨É© Ü­›¯Q©¬ g?G›ð•:YmPeEQ\ëëë©ÅX,…«L'Zjy¥²¡\X‰; ·` µ>©dp>)æÀy0à<¬ß[wþOæè㫎9V‰æüâ‡cœŽ9æÀ阧cŽ•Ûþ/Àf÷¡Î¢0IEND®B`‚keystone-2014.1/doc/source/static/default.css0000664000175400017540000000707712323716267022316 0ustar jenkinsjenkins00000000000000/** * Sphinx stylesheet -- default theme * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: sans-serif; font-size: 100%; background-color: #11303d; color: #000; margin: 0; padding: 0; } div.document { background-color: #1c4e63; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 230px; } div.body { background-color: #ffffff; color: #000000; padding: 0 20px 30px 20px; } div.footer { color: #ffffff; width: 100%; padding: 9px 0 9px 0; text-align: center; font-size: 75%; } div.footer a { color: #ffffff; text-decoration: underline; } div.related { background-color: #133f52; line-height: 30px; color: #ffffff; } div.related a { color: #ffffff; } div.sphinxsidebar { } div.sphinxsidebar h3 { font-family: 'Trebuchet MS', sans-serif; color: #ffffff; font-size: 1.4em; font-weight: normal; margin: 0; padding: 0; } div.sphinxsidebar h3 a { color: #ffffff; } div.sphinxsidebar h4 { font-family: 'Trebuchet MS', sans-serif; color: #ffffff; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { color: #ffffff; } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 10px; padding: 0; color: #ffffff; } div.sphinxsidebar a { color: #98dbcc; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } /* -- body styles ----------------------------------------------------------- */ a { color: #355f7c; text-decoration: none; } a:hover { text-decoration: underline; } div.body p, div.body dd, div.body li { text-align: left; line-height: 130%; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Trebuchet MS', sans-serif; background-color: #f2f2f2; font-weight: normal; color: #20435c; border-bottom: 1px solid #ccc; margin: 20px -20px 10px -20px; padding: 3px 0 3px 10px; } div.body h1 { margin-top: 0; font-size: 200%; } div.body h2 { font-size: 160%; } div.body h3 { font-size: 140%; } div.body h4 { font-size: 120%; } div.body h5 { font-size: 110%; } div.body h6 { font-size: 100%; } a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: #c60f0f; color: white; } div.body p, div.body dd, div.body li { text-align: left; line-height: 130%; } div.admonition p.admonition-title + p { display: inline; } div.admonition p { margin-bottom: 5px; } div.admonition pre { margin-bottom: 5px; } div.admonition ul, div.admonition ol { margin-bottom: 5px; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre { padding: 5px; background-color: #eeffcc; color: #333333; line-height: 120%; border: 1px solid #ac9; border-left: none; border-right: none; } tt { background-color: #ecf0f3; padding: 0 1px 0 1px; font-size: 0.95em; } .warning tt { background: #efc2c2; } .note tt { background: #d6d6d6; } keystone-2014.1/doc/source/static/tweaks.css0000664000175400017540000000310312323716267022152 0ustar jenkinsjenkins00000000000000body { background: #fff url(../_static/header_bg.jpg) top left no-repeat; } #header { width: 950px; margin: 0 auto; height: 102px; } #header h1#logo { background: url(../_static/openstack_logo.png) top left no-repeat; display: block; float: left; text-indent: -9999px; width: 175px; height: 55px; } #navigation { background: url(../_static/header-line.gif) repeat-x 0 bottom; display: block; float: left; margin: 27px 0 0 25px; padding: 0; } #navigation li{ float: left; display: block; margin-right: 25px; } #navigation li a { display: block; font-weight: normal; text-decoration: none; background-position: 50% 0; padding: 20px 0 5px; color: #353535; font-size: 14px; } #navigation li a.current, #navigation li a.section { border-bottom: 3px solid #cf2f19; color: #cf2f19; } div.related { background-color: #cde2f8; border: 1px solid #b0d3f8; } div.related a { color: #4078ba; text-shadow: none; } div.sphinxsidebarwrapper { padding-top: 0; } pre { color: #555; } div.documentwrapper h1, div.documentwrapper h2, div.documentwrapper h3, div.documentwrapper h4, div.documentwrapper h5, div.documentwrapper h6 { font-family: 'PT Sans', sans-serif !important; color: #264D69; border-bottom: 1px dotted #C5E2EA; padding: 0; background: none; padding-bottom: 5px; } div.documentwrapper h3 { color: #CF2F19; } a.headerlink { color: #fff !important; margin-left: 5px; background: #CF2F19 !important; } div.body { margin-top: -25px; margin-left: 230px; } div.document { width: 960px; margin: 0 auto; }keystone-2014.1/doc/source/static/nature.css0000664000175400017540000001015312323716267022155 0ustar jenkinsjenkins00000000000000/* * nature.css_t * ~~~~~~~~~~~~ * * Sphinx stylesheet -- nature theme. * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: Arial, sans-serif; font-size: 100%; background-color: #111; color: #555; margin: 0; padding: 0; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 {{ theme_sidebarwidth|toint }}px; } hr { border: 1px solid #B1B4B6; } div.document { background-color: #eee; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 30px 30px; font-size: 0.9em; } div.footer { color: #555; width: 100%; padding: 13px 0; text-align: center; font-size: 75%; } div.footer a { color: #444; text-decoration: underline; } div.related { background-color: #6BA81E; line-height: 32px; color: #fff; text-shadow: 0px 1px 0 #444; font-size: 0.9em; } div.related a { color: #E2F3CC; } div.sphinxsidebar { font-size: 0.75em; line-height: 1.5em; } div.sphinxsidebarwrapper{ padding: 20px 0; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: Arial, sans-serif; color: #222; font-size: 1.2em; font-weight: normal; margin: 0; padding: 5px 10px; background-color: #ddd; text-shadow: 1px 1px 0 white } div.sphinxsidebar h4{ font-size: 1.1em; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p { color: #888; padding: 5px 20px; } div.sphinxsidebar p.topless { } div.sphinxsidebar ul { margin: 10px 20px; padding: 0; color: #000; } div.sphinxsidebar a { color: #444; } div.sphinxsidebar input { border: 1px solid #ccc; font-family: sans-serif; font-size: 1em; } div.sphinxsidebar input[type=text]{ margin-left: 20px; } /* -- body styles ----------------------------------------------------------- */ a { color: #005B81; text-decoration: none; } a:hover { color: #E32E00; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: Arial, sans-serif; background-color: #BED4EB; font-weight: normal; color: #212224; margin: 30px 0px 10px 0px; padding: 5px 0 5px 10px; text-shadow: 0px 1px 0 white } div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; } div.body h2 { font-size: 150%; background-color: #C8D5E3; } div.body h3 { font-size: 120%; background-color: #D8DEE3; } div.body h4 { font-size: 110%; background-color: #D8DEE3; } div.body h5 { font-size: 100%; background-color: #D8DEE3; } div.body h6 { font-size: 100%; background-color: #D8DEE3; } a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: #c60f0f; color: white; } div.body p, div.body dd, div.body li { line-height: 1.5em; } div.admonition p.admonition-title + p { display: inline; } div.highlight{ background-color: white; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre { padding: 10px; background-color: White; color: #222; line-height: 1.2em; border: 1px solid #C6C9CB; font-size: 1.1em; margin: 1.5em 0 1.5em 0; -webkit-box-shadow: 1px 1px 1px #d8d8d8; -moz-box-shadow: 1px 1px 1px #d8d8d8; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ font-size: 1.1em; font-family: monospace; } .viewcode-back { font-family: Arial, sans-serif; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } keystone-2014.1/doc/source/static/header_bg.jpg0000664000175400017540000000723212323716267022553 0ustar jenkinsjenkins00000000000000ÿØÿàJFIFddÿìDuckyPÿîAdobedÀÿÛ„      ÿÀ¡åÿÄu !1AQa"q‘2¡BR±ÁbÑ!1ÿÚ ?ÿez«F•ºñU®«þO¥¯’ôª»8H+Í{|m¶µfu7‡uÚ›â´k$+ËÙÑNîÚ7n. aÛíUBªn\jgZÂË’i8XÅÔëJ5û•ì­.ši?Râ¾wmR­|+5ÆëŸ:Î…ÄÇ.ÎËV¿«ù‰^=PW®„¯ 'fòˉ­^½|¡{—¦rTsµaµƒ§õ«7¾&3!¬}¾‡5kt´1é¼w§¶êÍ7ÇZ‘ZïªìMªñZÀG‚µŒ?85„o©¨ëQ:ÈÑÕFœ_¢fF;õÝ’ÊA^>ΚöRË·­Z¯Fö6λ[¯¯¯­Ó®©? BhìúíØ¢IUÆ©ÑÇê½wzW\寱3ÅÖé¤Á8Ë–ˆ±µV¬£Gª ô% ZßY Ý:ù&ëíâõdWu×¼Kÿo$iß±ã$=¸Æ|‘^ªÄJhŠè•–ú²+ºªI$¢6#xë_Á´· ÛÊÓè@H €è´"º¯M¶‰ªÚ6ˆ(P?×­ÂVQSèî¾S.½´˜Å–%/×ÉRÉ;V®oê*nQS¹UÛ©5ÖÞ4b§ËUéïm7\<ì1ô¨ÛÛLÖñÙ&§L]p³µªÍM#²Sö­ ‰\/WÂbxæ6Ýù4¨õYüe{)~¸µ«þÙŸ¨»+~ÎÇÙeñöjÒÂ.&·×T«ÊÊ^œ¢ 9ß­6­—®>¡#Ïý_›åu½fµZ¬fCXú´V£WÞTǃ;f¾…l­”Ÿ¹ÎšÕÇ^/;‘cÄèÕ´ÞMb-:›¬é®ƒtnYZ­H°¼º6—£:+=5E¬Âµ­oíöãH«ëD´_°WÊ)÷-4 ‹–ç@7W¨V¸»)o@ Ù¸®g}ˆ¯M:×rM¿?r5¥Æ4Y§|ìEz'ðA®>å÷#NêœaVðŒÖ³ЧŒ}Âæ;q˜’4è«m" “ÓÀU€4½H­/@®©mimPü«¸ÿÑÝ_.8öÖÎ×%: ±Ö•N‰n)ŠVÕ«ˆã¼’‘äì·b´üxò‹šš¿Ô—Ûf÷ÿM\}íVœbR&+¥öe¾ŒŽ鉬é¹jk]•t¯R†Ú‹l?ª•£…¼L®IºM|¢R9öV½“gûÌñÚ šÎáñ|‰l£ –§J­¢%¿$¤z+Ò—¤¨`úu‡ ¤{zªø,çs:ÖcQdó¦ÆZyûzšº´ÂƒXÎã|RXήF®c_uÿhÜŠí×dÓú—XJÏiô a®Jì+ÓEjÕ¤§‚8Þ¶öÅ5SkiV¡¤ß¨x§õô"±ñ¹÷)…0Um FÞÖ=”ëÆ}ÒA§MWJÕ7¡7GkQ5¡–£\s0=¬µ8ô#yBK[Y¢InA¤¿É…° 6‘´¾ÀlŠÒ*¶@Ë©×ÙÉÖf‘‰;uó£_ÚrJFø:ÖZŸ"ý¢kBR-ºÖ-Œ¸Gž”ìëí\3eŒ—²Õ³´Û_]Œ·,î’VÑnäínØ®'V17®µ (äµZ•#/®ªó„ül Ä¿O[i¬7ûFå"Wªÿ,èþ¿R¿ÉÉ5«˜Ý¿¯Æü—í¤1‹âæÜ´@‰W[ak±sHôuEuÜ,uQiªqVýo†V}IR8®¼W «½o•œÏŠì_«ÚÓßV* ªuXð(źÖ^¬§³{)JüjÚùQÝXêå¯EE}Iïþ"‘WRQ 'TJAtOºº§ GeÓ;d•¬Ç¦Q†fµ˜[ªZàR"ëi¸޵­œâ ZŽŠ’ÆǦµxÁ¨s¤¨Éà*…tH‚¤Ò"¬i[ ÒA"€ùÚ­š:õÀ¼Z@E_(+JµÅïÅûk/È£ÎÛ•d¡ùA˜÷&ï×YSäkOM:å5¶Äªó÷ÑÖÏgè3QƵ®#öòR9Þ¼lü±š›ˆèÜ$ç\‘WUÛ^î*3‘Ú”t|k§“:Ö:qvÍÞ|Ö¸(„ä¡ UÍùZŠ3Z©«†›^Šõ[0–Iº;>¹¬FR%#‚¤V¥£J¯À¤/I«ÓBR"£i'®Â‘›uk0ŸE#¯]y%Hã—£&®cº¥SÑ61j>S°¤eÖ6yܔޕ£1àµc²Kz§¡/üf‰6çÀWXü…*ú;ª/GU_@Ö,?UKòPâEi( ´–€m 4ˆ­ ,¢¡@ø++$ë]YÖâÜråj¥[WîDŽí]WÔU‚£j&?ôéNªÑÎïrâú¢^”×^•+ŽËAºcЕ¦Sˆ%W>Îm¿l§û03ZÖWSËݶwŒ®¹†¼–޵£OÓrQ¼LDúŠE¯[k/ìMÒ5ñÎī֣+AHU9Ó @G¢µ•à5˜ZjÖëÁ9¥å#PžVA× …‡ †¥4¿Ú«ü07Ïк ±Ó‰ŠÅx…i 7"Å X`^$üëëþǫťGøÇ¸ÈRЇ\áUWЮ€Žª¾Ð¢¬Oä}€Ë¢ ±ä ÁÄŠªâx8‚@¼}×Z„€BU ¼H4¨E(U†âQaP>7Ñåˆ×EIª  „â—×Ô+Qè•@¼@q:ýÀœ@¼Y‰U¤€°B}^, Ä @Rãè@â¡^( ‰âˆSˆ|èFÞl€kXªþ@©}ªë €,¨ÄêB$0Œ…j@©@,0«Ä ª€,` ‹(†4Ä8Š//,âh@Ò@XdR!ô @J¤"À°‚ <Ði˜@€°üX Qa! «PH @ XaH`X*,P ‚ €E‚„‚*à ¢ÀE @P TX €,‚€E ÍZÏb£IÛÁ ÿÙkeystone-2014.1/doc/source/static/jquery.tweet.js0000664000175400017540000001635312323716267023161 0ustar jenkinsjenkins00000000000000(function($) { $.fn.tweet = function(o){ var s = { username: ["seaofclouds"], // [string] required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"] list: null, //[string] optional name of list belonging to username avatar_size: null, // [integer] height and width of avatar if displayed (48px max) count: 3, // [integer] how many tweets to display? intro_text: null, // [string] do you want text BEFORE your your tweets? outro_text: null, // [string] do you want text AFTER your tweets? join_text: null, // [string] optional text in between date and tweet, try setting to "auto" auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with" auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:... loading_text: null, // [string] optional loading text, displayed while tweets load query: null // [string] optional search query }; if(o) $.extend(s, o); $.fn.extend({ linkUrl: function() { var returning = []; var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; this.each(function() { returning.push(this.replace(regexp,"$1")); }); return $(returning); }, linkUser: function() { var returning = []; var regexp = /[\@]+([A-Za-z0-9-_]+)/gi; this.each(function() { returning.push(this.replace(regexp,"@$1")); }); return $(returning); }, linkHash: function() { var returning = []; var regexp = / [\#]+([A-Za-z0-9-_]+)/gi; this.each(function() { returning.push(this.replace(regexp, ' #$1')); }); return $(returning); }, capAwesome: function() { var returning = []; this.each(function() { returning.push(this.replace(/\b(awesome)\b/gi, '$1')); }); return $(returning); }, capEpic: function() { var returning = []; this.each(function() { returning.push(this.replace(/\b(epic)\b/gi, '$1')); }); return $(returning); }, makeHeart: function() { var returning = []; this.each(function() { returning.push(this.replace(/(<)+[3]/gi, "")); }); return $(returning); } }); function relative_time(time_value) { var parsed_date = Date.parse(time_value); var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); var delta = parseInt((relative_to.getTime() - parsed_date) / 1000); var pluralize = function (singular, n) { return '' + n + ' ' + singular + (n == 1 ? '' : 's'); }; if(delta < 60) { return 'less than a minute ago'; } else if(delta < (45*60)) { return 'about ' + pluralize("minute", parseInt(delta / 60)) + ' ago'; } else if(delta < (24*60*60)) { return 'about ' + pluralize("hour", parseInt(delta / 3600)) + ' ago'; } else { return 'about ' + pluralize("day", parseInt(delta / 86400)) + ' ago'; } } function build_url() { var proto = ('https:' == document.location.protocol ? 'https:' : 'http:'); if (s.list) { return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?"; } else if (s.query == null && s.username.length == 1) { return proto+'//twitter.com/status/user_timeline/'+s.username[0]+'.json?count='+s.count+'&callback=?'; } else { var query = (s.query || 'from:'+s.username.join('%20OR%20from:')); return proto+'//search.twitter.com/search.json?&q='+query+'&rpp='+s.count+'&callback=?'; } } return this.each(function(){ var list = $('
    ').appendTo(this); var intro = '

    '+s.intro_text+'

    '; var outro = '

    '+s.outro_text+'

    '; var loading = $('

    '+s.loading_text+'

    '); if(typeof(s.username) == "string"){ s.username = [s.username]; } if (s.loading_text) $(this).append(loading); $.getJSON(build_url(), function(data){ if (s.loading_text) loading.remove(); if (s.intro_text) list.before(intro); $.each((data.results || data), function(i,item){ // auto join text based on verb tense and content if (s.join_text == "auto") { if (item.text.match(/^(@([A-Za-z0-9-_]+)) .*/i)) { var join_text = s.auto_join_text_reply; } else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) { var join_text = s.auto_join_text_url; } else if (item.text.match(/^((\w+ed)|just) .*/im)) { var join_text = s.auto_join_text_ed; } else if (item.text.match(/^(\w*ing) .*/i)) { var join_text = s.auto_join_text_ing; } else { var join_text = s.auto_join_text_default; } } else { var join_text = s.join_text; }; var from_user = item.from_user || item.user.screen_name; var profile_image_url = item.profile_image_url || item.user.profile_image_url; var join_template = ' '+join_text+' '; var join = ((s.join_text) ? join_template : ' '); var avatar_template = ''+from_user+'\'s avatar'; var avatar = (s.avatar_size ? avatar_template : ''); var date = ''+relative_time(item.created_at)+''; var text = '' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ ''; // until we create a template option, arrange the items below to alter a tweet's display. list.append('
  • ' + avatar + date + join + text + '
  • '); list.children('li:first').addClass('tweet_first'); list.children('li:odd').addClass('tweet_even'); list.children('li:even').addClass('tweet_odd'); }); if (s.outro_text) list.after(outro); }); }); }; })(jQuery);keystone-2014.1/doc/source/static/header-line.gif0000664000175400017540000000006012323716267023005 0ustar jenkinsjenkins00000000000000GIF89a€Åâêÿÿÿ!ù,ŒËéQ;keystone-2014.1/doc/source/middlewarearchitecture.rst0000664000175400017540000000256112323716267024134 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ======================= Middleware Architecture ======================= Abstract ======== The Keystone middleware architecture supports a common authentication protocol in use between the OpenStack projects. By using Keystone as a common authentication and authorization mechanism, the OpenStack project can plug in to existing authentication and authorization systems in use by existing environments. The auth_token middleware is no longer hosted in Keystone and has moved to the python-keystoneclient project. The `documentation regarding authentication middleware`_ can be found there. .. _`documentation regarding authentication middleware`: http://docs.openstack.org/developer/python-keystoneclient/middlewarearchitecture.html keystone-2014.1/doc/source/conf.py0000664000175400017540000002223012323716267020154 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # # 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. # # keystone documentation build configuration file, created by # sphinx-quickstart on Mon Jan 9 12:02:59 2012. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) # NOTE(dstanek): path for our # Sphinx extension # NOTE(dstanek): adds _ to the builtins so keystone modules can be imported __builtins__['_'] = str # -- General configuration ---------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', 'oslosphinx', # NOTE(dstanek): Uncomment the [pbr] section in setup.cfg and # remove this Sphinx extension when # https://launchpad.net/bugs/1260495 is fixed. 'ext.apidoc', ] todo_include_todos = True # Add any paths that contain templates here, relative to this directory. # if os.getenv('HUDSON_PUBLISH_DOCS'): # templates_path = ['_ga', '_templates'] # else: # templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'keystone' copyright = u'2012, OpenStack, LLC' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['old'] # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. modindex_common_prefix = ['keystone.'] # -- Options for man page output -------------------------------------------- # Grouping the document tree for man pages. # List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' man_pages = [ ('man/keystone-manage', 'keystone-manage', u'Keystone Management Utility', [u'OpenStack'], 1), ('man/keystone-all', 'keystone-all', u'Keystone Startup Command', [u'OpenStack'], 1), ] # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme_path = ["."] # html_theme = '_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['static', 'images'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1" html_last_updated_fmt = os.popen(git_cmd).read() # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'keystonedoc' # -- Options for LaTeX output ------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples (source # start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', 'keystone.tex', u'Keystone Documentation', u'OpenStack', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for Texinfo output ----------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'keystone', u'Keystone Documentation', u'OpenStack', 'keystone', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # Example configuration for intersphinx: refer to the Python standard library. #intersphinx_mapping = {'http://docs.python.org/': None} intersphinx_mapping = {'python': ('http://docs.python.org/', None), 'nova': ('http://nova.openstack.org', None), 'swift': ('http://swift.openstack.org', None), 'glance': ('http://glance.openstack.org', None)} keystone-2014.1/doc/source/index.rst0000664000175400017540000000441012323716267020516 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ==================================================== Welcome to Keystone, the OpenStack Identity Service! ==================================================== Keystone is an OpenStack project that provides Identity, Token, Catalog and Policy services for use specifically by projects in the OpenStack family. It implements `OpenStack's Identity API`_. This document describes Keystone for contributors of the project, and assumes that you are already familiar with Keystone from an `end-user perspective`_. .. _`OpenStack's Identity API`: http://docs.openstack.org/api/openstack-identity-service/2.0/content/ .. _`end-user perspective`: http://docs.openstack.org/ This documentation is generated by the Sphinx toolkit and lives in the source tree. Additional documentation on Keystone and other components of OpenStack can be found on the `OpenStack wiki`_. Also see the :doc:`community` page for other ways to interact with the community. .. _`OpenStack wiki`: http://wiki.openstack.org Getting Started =============== .. toctree:: :maxdepth: 1 setup installing configuration configuringservices community Man Pages ========= .. toctree:: :maxdepth: 1 man/keystone-all man/keystone-manage Developers Documentation ======================== .. toctree:: :maxdepth: 1 developing architecture middlewarearchitecture api_curl_examples apache-httpd external-auth event_notifications extension_development Code Documentation ================== .. toctree:: :maxdepth: 1 api/modules Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` keystone-2014.1/doc/source/images/0000775000175400017540000000000012323716511020113 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/source/images/graphs_authCompDelegate.png0000664000175400017540000014460312323716267025420 0ustar jenkinsjenkins00000000000000‰PNG  IHDRß‚Îx‡gAMA± üasRGB®Îé cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿÿÿÿ X÷Ü€IDATxÚìe@ÍÛÆ/ºiÄ»»E[»;ÁÄÅnÅDì.l±»PJ:¥öý°ÏýŽÿƒçE}æ÷e9œÙÙÙÙ=çÌ^sÏuËÿ‡Ãáp8‡Ãáp8‡ÃápþdKº‡Ãáp8‡Ãáp8‡Ãá'\øæp8‡Ãáp8‡Ãáp8Î_¾9‡Ãáp8‡Ãáp8‡óWÁ…o‡Ãáp8‡Ãáp8‡ÃáüUpá›Ãáp8‡Ãáp8‡Ãáp8\øæp8‡Ãáp8‡Ãáp8Î_…|I7€Ãáü>x{{{{{gΜ9sæŒôr222222€ŠŠŠŠŠ `lllll ´k×®]»v@ÇŽ;vìøóÛ{éÒ¥K—.sæÌ™3g°mÛ¶mÛ¶––––––%Ý›…XYYYYY}=Úuãü))))))@NNNNN §§§§§WÒ­âp8‡Ãáp8ç÷‚G|s8œÿçÕ«W¯^½®\¹råÊ@VVVVV—————g[999999 &&&&&ؽ{÷îÝ»WWWWWW`Ê”)S¦LùùíeíMOOOOO/é^,œƒ £££££´nݺuëÖÀ“'Ož}úô¿ÿº>|øðáëGê?êO:ÎêÕ«W¯^Í,[$Ù¼yóæÍ›Y»ÉúE$ôK«ïgï¦M›6mÚT®\¹råʬßK•*UªT) wïÞ½{÷.ѽbÅŠ+VÎÎÎÎÎÎìÿµk×®]»6» òþ?~üøñãkkkkkk¶€VFL:uêÔ©ì>äp8‡Ãáp8ço‚[p8œ&;;;;;زeË–-[˜ (éaMÅmÚ´iÓ¦ p÷îÝ»wïÆ 6lP¶lÙ²eË—/_¾|ù20|øðáÇ?~üøñ#0wîܹsç½]$ ÖªU«V­Z€‚‚‚‚‚0qâĉ'jjjjjjÀž={öìÙ´hÑ¢E‹ÀÉ“'Ož< ´lÙ²eË–¬¾ðððððp F5jÔ`žÙd ¢­­­­­ ,_¾|ùòåÌBäáÇ>¼¼¼¼¼¼Xÿ?~üøñãlKåß~ÝÈâ¥Aƒ 4âããããã™K×…&¨¿Šâ>_òt2dÈ!C˜À=jÔ¨Q£F±û”î›Ç?~ü˜m)é(%µ¤ûˆÊ“NŒ7nܸqÀÖ­[·nÝÊ„~º¿è|.\¸páBVïš5kÖ¬Yóëú™Ãáp8‡Ãáp8œŸ ¾9ŽTfÏž={öl&ð‚ ‚$&&&&&çÎ;wî‹„&ÓÌÌÌÌÌŒí·sçÎ;wW¯^½zõ*ó¢¦ibèСC‡eVÞÞÞÞÞÞìÿ&&&&&&…·Ÿ"¨I8%ºtéÒ¥K—fåFŒ1bÄ ~ýúõë×gÂá‹/^¼xÁÊÍ™3gΜ9@fffff&‹0—ô'Á”,X|}}}}}Ùþ, e«V­Zµjõß¹nù\¿~ýúõë@ݺuëÖ­Ëê£yšÅ}¾û÷ïß¿?`cccccøùùùùù<.õ;ExSD¼¹¹¹¹¹9àäääääÄÊÓ„NÍš5kÖ¬ÉþOÇëÕ«W¯^½€ ,X°€½?`À€ùùùùùùì:p8‡Ãáp8‡ó7Á…o‡#ò¤AÖ......À¢E‹-ZtêÔ©S§NË=zôèÑ£,2š’'>zôèÑ£GËW­ZµjÕª@nnnnn.páÂ… .}úôéÓ§ôv‘ÀK‘ÔÁ˶’Ô©S§N:À²eË–-[¼ÿþýû÷Lx}úôi61 )x$wíÚµk×®€¿¿¿¿¿ÿÏï¿â>_šh9tèСC‡XD¸»»»»»;»¿ú÷ïß¿¶ý^èxGŽ9rä›Ðiß¾}ûöíÙyчÃáp8‡Ãáp8#\øæp8R¡Èfò&/à]»víÚµ‹Y_àÒ¥K—.]fΜ9sæL¶­P¡B… ˜¥ Y¢ueƒ$+W®\¹r%›È ž¬lh¢¡K—.]ºtaB;yÞs8‡Ãáp8‡ó7À…o‡Sd(© ed!BÞÇôJ:) Y+ØÛÛÛÛÛ3K†¢BI ƒŽCPd-%),*$ÌJÖ÷§ñ»]7ŠÈÏÊÊÊÊÊ*zû‹ ŠÌ–FqŸ¯dÄøÅ‹/^¼È"ËÉJ…"ÁW­ZµjÕ*àÞ½{÷îÝ+úD ѰaÆ aaaaaaÀ±cÇŽ;œ8qâĉÌâæÊ•+W®\aÉAÉû»°¤Ÿ‡Ãáp8‡Ãáü È–t8Ο y7jÔ¨Q£FÀ¾}ûöíÛ>|øðáÃË“‡1%‰¤H^Šx•ÜêêêêêêOŸ>}úô)“““““Sx»h?J’HI¥‡¶ýöíÛ·oß2KŠœÖ×××××/º'2yŒ“góïBI_7J²HýLB¸4 ëoI¡¶0A=*****JúûÅ}¾AþòåË—/_Í›7oÞ¼9°víÚµkס¡¡¡¡¡ì:$'''''³ý¢B‚>%Ť¤•äõM111111,)+ ò7nܸqãFqßm‡Ãáp8‡Ãá” \øæp8? x$@RrH²Ò Ú¶mÛ¶m[ =====E¶Jƒ’AöìÙ³gϞ̤0(©#yqS„í;wîܹS°}úôé’nçgaccccc4lذaÆ%݇Ãáp8‡Ãáp8Üã›ÃùΟ?þüy`þüùóçÏ/^¼xñb@L†XÒ­ÒÒÒÒÒÒ€víÚµkדս{÷îÝ»7+ׯ_¿~ýúFFFFFFÀÂ… .\XÒ­/1™˜›››››—t«ä9}äÈ‘#GŽ/^¼xñâ·×séÒ¥K—.sæÌ™3g°mÛ¶mÛ¶––––––%}–E'%%%%%ÈÉÉÉÉÉôôôôôôØûË–-[¶lû\ý-bRM`÷îÝ»wƒƒƒƒ1y& &Ÿd^ô•*UªT©RI·úçqåÊ•+W®^^^^^^ÀÆ7nÜ”+W®\¹r%Ý:‡Ãùï²~ýúõë×ûöíÛ·oß·ïo`````8pàÀ%}6œÂ8pàÀ™àÒ¥K—.]úíõœ9sæÌ™3€˜Ì»ðòb’t6¬[·nݺu1‰; & /éÞáHãwþâp8œo…G|s8ÿBLLLLL rJºU JòGí{ÿþýû÷ï –»{÷îÝ»w§OŸ>}ú´¤[]8$œÖ¯_¿~ýúÀž={öìÙSÒ­*ÈÛ·oß¾}Ëúÿ{‰eõ¤§§§§§—ôÙz€7oÞ¼yó¦`¹×¯_¿~ý¸víÚµk×JºÕ?΂ ,XÀ&ÂV­ZµjÕ*ö9#+ž%K–,Y²ptttttd+dID÷sjjjjjjI·ŠÃáp8ïÞ½{÷îû~ŽŽŽŽŽŽ>}úôéӧ·‰‰‰‰‰‰%}œ¢Bó?~üøñ÷×C÷ Ý7ÉÉÉÉÉÉ€¼¼¼¼¼|Á-cÏž={öìY`Ô¨Q£Fš5kÖ¬Y3ž¤üwåOyþâp8œo…{|s8ÿ(²–¤¿;Ÿ?þüù3póæÍ›7oÎÎÎÎÎÎ%Ý*Ž4H莌ŒŒŒŒ,éÖü|^¾|ùòåK`úôéÓ§Ogr~~~~~~le¼é'Nœ8qâD yóæÍ›7*V¬X±bÅ’>«â£uëÖ­[·f÷E™2eÊ”)SÒ­âp8Ž$—/_¾|ùrÁß-çß •£­ZµjÕª•ôr€»»»»»;pèСC‡±•’]ºtéÒ¥KIŸ ‡àÏ_ço…G|s8ÿHx266666.éÖp86.\¸pá@Faô(M8 ä«›6mÚ´iÛoÿþýû÷ï/é³)~ÔÔÔÔÔÔ˜7;_ÒÌáp8ÎUUUUUUfåG\½zõêÕ«%Ý:‡ÃáüWàÂ7‡S ‡ï„ &L˜À<ðÈ£™„òö=~üøñãÇ ¯—¼žË—/_¾|y@EEEEE¨S§N:u˜•BaT¨P¡B… Ì \äýH¨4`-[¶lÙ²eÙyååååååÜŸ"<{õêÕ«W/&*(((((°×ýû÷ïß¿?ÏöôèÑ£G öÿ)S¦L™2‘‘‘‘‘)¸D’–TNš4iÒ¤ILè§~§þ£ó+ Š\îÞ½{÷îÝæm9mÚ´iÓ¦I"„)"˜®»……………³Ø >‚– Óy>>>>>L(–Fhhhhh(»^ºººººº¬>jG`````à_I!WšÅ$UªT©R¥ óFíÙ³gÏž= –+®ûÙßßßßߟ}nH°755555eIbwîܹsçNö9'/Π¯PªŸ¬o9þäÉ“'OžHoE,6hРAƒì{K[[[[[›E”Ñ}Âáp8œŸ­ˆêСC‡Ø÷0}/S’êÂ,âÈ›š~¿—/_¾|ùrö»Eë²Öe­Ë*ø;' YµÈÊÊÊÊÊ-Z´hÑ¢…ôãÓ¸ˆ~ ¬]»víÚµ€“““““;?ÚV­ZµjÕªì÷P4AìéééééÉr(+++++³qƒäx"réw&œ©½”säwú… ë% 6lذ=¿ÐøÇÄÄÄÄÄ?~üøñã ·ÌÎÎÎÎÎfýKûSuìØ±cÇŽlAíº~ýúõë×Y=4¾¡÷©}Ò8zôèÑ£G¥×÷³Î—¬ésFŸ?úÜÐsÅ­[·nݺÅöûÞç/ è¨\¹råÊ•Ùu.UªT©R¥XΩÿÊŠP‡ó#p8©ˆ‚In‚ Z†,'&mQ°Q8qÀ+bRA½€A´q P°¾uëÖ­[·Ž·iÓ¦M›61™¢ ˆÂ² ¨«««««³rsçÎ;wnÁúDïeAhÛ¶mÛ¶m ¾/ ö¬Ö1i&{_äØþ¢º ˆÂ• ˆIPaÑ¢E‹-1¹ ˆKA@ ‚8 bõˆÉA\ÉŽ'>€°þA€ ‚8ðQèq€(¢0(¢Å«O´¨(Øb²PA#tYÿΜ9sæÌ™ì|D!’½/&1üþûLôÐcí£zÅ3AX½zõêÕ«Ùu¡rtÝ$iß¾}ûöíÙõ=û –—4 ‚80у±èí „Ù³gÏž=›µK|@QØfå‡ 2dÈÖ_â[úöíÛ·o_A#§A|`dõmÙ²eË–-/&Ýq€-â‚ ˆÉhAæ¡fÍš5kÖdŸ;ú<~/¢×¥ ˆÉ¢A| ñAD¡WÄ „¢×[Ü÷³ä÷—¡¡¡¡¡¡ ˆOì{äÙ³gÏž=qB‡}>?~üøñãGéí¥~¥ëEˆÂ>;®˜c€½/N‚8A!â„»V®\¹råJA'@ALŽ%áááááᬞ€€€€€v]kÕªU«V-¶?Ýt_ÐùøðáÇßý9çOEr¼õãõ>þüùóçìwQœH1ÒWÄ\‚`oooooϾ·é{\wÒ÷?mÇ7nÜ8A'4!Y?Y?Y_Ä ö;&‰h±ÁΛÆô»+ ýnŒ9räÈ‘ìÿ4¤zh\+ €‚ ˆ‚øÂ~OÅÀ‚DZ¶¶¶¶¶f¿ƒÔ?¢%š xxxxxx°ò÷ïß¿ÿ¾ ˆÂ¸ ˆB· ˆѬ<D—=G|/b NáÏCÒ çÚ×®]»ví*XnêÔ©S§Neåh¼Cã‰Â° 4jÔ¨Q£FÒ¯#íOׯ¹[·nݺu+ÛŸ®7WY=týè}j4$Ÿc$ë+îófØ}-H±ç8‹-ìþ qÕ·>IŽóèyÎ×××××WÄäæl|LÏÅ´?‡Ãáüj¸ðÍáü ß*|Ó@TLVX° LT 4„™À¡&Mš4iÒDú€Nòæ[…o.Å&LJ£OŸ>}úôa&Š/^¼xñbÖ1‰ŽôzÄa6@“DL†Çê#ATɸ´(Éþ’6ñ@fTŸ!\°\鯸…ï–-[¶lÙRºpJ8WR Ü»wïÞ½{Y}çÎ;wî\ÁzNœ8qâÄ VNŒ úööKÖ#F’,G÷•“A,Gpê_º_$¡û‘„{i‚& ÿ$ŒÒƒåBýE%t^´¥v‰Eì:K»®Å}?K~=zôèÑÒë“ü~#Ú –#áš$ÅÈ|ö~aÂ7 ô="F~<=hÒ}>cÆŒ3f°þ#aA\1 ý{’î z6lذaÃ~üús8Ο†ä¸qРAƒ „1cÆŒ3Fú–„XiÐø’¾×éwBú}733333cßã’¿‹’‡>|ø°ôã“ H‚Ÿ$ôû'®xbõÒD5ñâÅ‹/^°÷O:uêÔ)6Ž ßú]— ÔT Ӓ𭨨¨¨¨XøD„¸r“6ˆÉ¤ –“—·ðÝ£G=z°‰ÉíØ±cÇŽË~Ÿi?1ibÁëMãz™ö¾¸"–½?oÞ¼y󿬇®«dÀÅϾ‹û|i¼FïK ¬¢û›&LÄÈìý¢>ÑÄ éÒ À¾éù‰Ãáp~5Üê„Ã)FhI"YbHbkkkkkË^‹‘Òìõ;wîܹ$$$$$$°¥ž¢ðS°>ñäûÛ+F¾²%”Ç>|¸ôòduBÖ´“,^Èò,]$¡$7´”Nο¿ý´”–òÑÒWZ²'¹¥¥§´TOrI,õ]'ñAªàqÉ*¢S§N:uúþöKƒ–4Ò’\IÄ$fIröìÙ³gϲ÷ňo@Œ—î%Mÿ'k²ùUˆÂuÁÿÓýA–b„5{_üùb–AÕªU«V­ N8¼î¢ Ë,‚h)vQ-J¤AýÌî1¢ˆÝ”ÄI|Pdí Ï9QÜ÷³$…%¡'ÈØR[JB%‰äÒmJÚYTD!µ‡<Ð%¡%àAAAAAA€ø ͬOȺ„–ô>}úôéÓ§û‰î ú~¦d¿‡ó_GŒÐÄ@ é[qåYÁý)ÞùóçÏŸ?tíÚµk×®€(l,O¿ï#FŒ1bû§ßiIÈb¡0k1`'Z ZBµ «É MÒ‚‚΃¬&hHÉáEáؼyóæÍ›¥·G2™|aã]ú}’–+„~ç/^¼xñâEÀÕÕÕÕÕ•Y„IBÖ†Ò~_q"WVÜ’SÉÚ/9¾¥ñ=ˆ+d¥hN–%’¿ë4#èºK»N4®þU÷ù–.]ºtéÒì5%QøðáÇÙ¸Y ü^¿~ýúõëïO^IÇ#kF1ðªà¸š¬-iÜFçÁáp8¿ù¯‚Ãáä-, òº&$½”% b$ˆôúÈûWÒ;¯¨ˆKÜØkš¤Aris:?‘9 ƒä‘'FXüx“GpRRRRRàèèèèèXôýÅHЂý_X?äí^܈+¤¿/Ù>1rŸ½¦:ò.$á•<¡é¾;vìØ±cÇ Ÿð(nh„<¥A÷5ys$“§9 ¾ß{ýEkžï?zp¢oÚJ^qe»bóâ.îûY’¢&·%^\ªÊ¼øÅ¥æÌ£œ|ú* òÚ¤‰Œ¢~ÎHà'$½ÚiB޶…!ù=Ìáp8ÿUèw‡G¢ÛR=‡ˆ+>™g9‡Ãáüj¸ðÍá#…%kùÖý³²²²²² ßfò¿•âJÎH7E^ÒÀ–’¨P²z!Á•’}/4Цi‘ÍÒ|УþÿÙý^’É%‘|p¶"€’'RòB éÁI\rÌ„Î_…´öÉHÑc“%ƒ,*”|ö[¡ä¦ô A‘kÒ ˆzÑkxõêÕ«W¯Øƒ³äy×ý,‰dš4(Ù$'}^éóLØ¢UMÑÛW؃ÿ÷ÖCB†´‡Ãù:$ìÒ ±oErTÔq°äøS´ú(X®¨¿[1M¿ƒ”¬_ª‡Æ¡¢å‹Ü¦€ Š sNEþHFžSÿÓy-Ñ-nDÏnéïKFxK‹üiÖ¬Y³fÍØƒ ˜¡DV"Ò¬i~Wè:ÒÀŸúKÚu§-=ÓõýÞ‰*ZB+zþ€# -M–| -îûù{¡ÏäD­ Ï¹èñXôz)ҟο°ïBLÞÉ–NK.¡ONNNNN.üúÓŠI‹)‡Ãá|$€‘p]ظ• «âG#Aé÷œÆ™4ÑõêÕ«W¯²ß3ú"á›~(@@ô8.h FõàMã^š&K²vøÞ‰iÐ8ŽÆ=EíçŸ5N- üiüOã.z-‰äï:«¤ýž“5ÞÐu#h\Lõ6Þ(ì}ɉ‰Â&D¯véï÷ùÒ ЩÿIx=çÑãÐÑÑÑÑÑa+¿ŠX§•ô¹£€&ºïè9Æiôùáp8œ_ ¾95B (1Ÿc>Ç|Nž=yöäY wÍÞ5{×ä{Ê÷”ï hûhûhû‹ ,6øñã~/40§Š•&¬mذaÆ ßX°ò¢`W°]bd‹ ˆ‚0tèСC‡ ‚(0 ‚é.âWÖ_t|q « ˆKOÙñÄ$7' ¤‚ k‚ F±,õ¢)¢g¢ ˆ‘«‚ ¿ÿ>“±öÑyÓñÄ¥¡‚ zç±ó=£ ¯ÿæÍ›7oÞ,x¿S–úEœY½âŽ ˆ’¬œèñÇί0š6mÚ´iSA#W ¾/>Ð ‚–––––– ˆ^ ¬ŸÄ¥œ‚ >°öÑçú{A®Y½ôy“‹ ‚hÁ"uëÖ­[·.»n¢`,bD «·¸ïgÉï/12¼èç)>P³Ï=ÕCß Ò Ï=•“±÷ÅÈ/Ö_ôù¦û™î{Ñ+VD[ĉ3Vø`ÉúI| cß7b„¸ ˆÂ »?ž?þüùóï¿þ‡ó§"F*³ïgqBñÇë¥ß1ÒYÄAWF±ïcŠ˜ ˆ+Ð Ö7`À€‚(нô;A¿ tžâÄÁò¢Ç1+GãI¨ŸDo6Ž¥qãzõêÕ«W/Önê1§GÁzÅÈdA“¥~~’¿Ÿ4®…Oö@ã"j§¾—mÛ¶mÛ¶­ðç!iˆ+ÇØþ4.-?X9çS91’XÄ@AW€±q$Å •‚Ç“<²úèúP}âD¼ ˆ+X9Ñû½`}¢ ÎÊÑxlÑ¢E‹-bã_1R»ðúŠë|i Ôèø$ˆ‰Là– ñôàEǧ 1û» ˆÙë‹_ø¦ëN< ÈéºÐÀò[¡$˜ôà"F¢‚˜LˆÝ7Dq ß„¸tS\]]]]]Ù!Gô˜”~Ÿ}/bd ˆLl‚Šîºn$¼Ò}#)àJR\÷ó ß„èÝÏ&ؤMT… ß Ðô FlÔâ ŒÂ'hHÐ#‹ØýGüô½'Z5ßõçp8œ?Ÿ%|Ož 5Ck†Ö @ÓYÓYÓ@”A™’î}Ο %=¤$B111111€hñýI 9‡Ãáp8‡Ãápþ¸ðÍù£°¹lsÙæ2€øÐúCë­)ƒ§ ž2ØéºÓu§ë÷×ÿ!ýCú‡t@ö¤ìIÙ“€ô=é{Ò÷‰Ú‰Ú‰Ú@Ì”˜)1S€ÈðÈðÈp ¤]H»v@ð©àSÁ§€§ež–yZX·.n] `ö`ÏŒF4¢ŒÀŒøbûv¥ìJÙ•*u«Ô­R7Àþ’ý%ûK€µµµPfE™eVFÙFÙFÙ€^½þzýÍ@Í@Í@@IFIFI¦¤¯çW#& Ĥ“€è‘ xyyyyy•të8‡Ãáp8œßÑ sšbNŸ’n‡ÃápŠ îñÍù«ˆW‹W‹WØ,°Y`,{²ìɲ'…ïgXÞ°¼ay úyôóèç?¯}éGÓ¦R2R2R2€ø>ñ}âûƒ>} Þ;¾w|ïÈ"Û_Ƚ{!<ñxÄã@ÄçˆÏŸ¿ý¸!!!€S]§ºNuÀVÃVÃV°ô°ô°ôLÂLÂLƒÖ­ ZÚǵk4ïiÞÓ¼À†à‘‡óãÈå"@tõí·%”tc8Nq¢ºÆA§ÂX@³ZmŸÚ~%݇Ãá•5^ØWy ö]I·†Ãá…®†-”§rse#dU ¾Ï…oÎ_Mªwªwª7°fíšµkÖS#§FN,X®‘u#ëFÖ@àÛÀ·oKºÕ…“}=ûzöu ýmúÛô·@bóÄæ‰ÍØ#±Gb‘†‘†‘†@è¬ÐY¡³€à˜à˜àài§§žv\xpáÁ 7$7$7äÛoÛ̶™m3 ’O%ŸJ>€}š}š}`ãfãf㔹QæF™€qeãÊÆ•Ý ºt7222€J'•N*Jº9§äÈ2y‹·‚v—•)ËWæp8Z§êjÕé TY|=鯮’nͯçÊ•+W®\a+Í6nܸqãF \¹råÊ•cåRRRRRRX======öþ²eË–-[œ?þüùóÀéÓ§OŸ>ýóÛtéÒ¥K—.,7ÊàÁƒüýõ8pàÀ,¢xéÒ¥K—.ýùçSÜvÝV®\¹råJàÌ™3gΜùu×­0222222??????vŸ&$$$$$@ãÆ7n ¸¹¹¹¹¹JJJJJJÒë ¬¬¬¬¬¬~Ýù”Ôqÿv\-ÆÞÜx€áá<¹)‡óGp¥ñ¶KcíómÆÙº_ÉeÆ­N85žžžÀÏ)žS|ûx!¼^Àƒ;w €ƒŽ:~Q¡)LaZx;ÔÕÕ§qNãœÆ‚+Wl›Ú6µm X°<`y010101 fÌ4˜ hÔþ¨ýÐê£ÕG«OI_ ‡Ãùqªoàxí% ¼Åò’…zI·†Ãá|OÊ´vv] ž"¹¤[SrpLÂbjjjjj*{?88888hÖ¬Y³fÍ€8p  €úúõëׯ_×®]»víÚ¯kÿçÏŸ?þÌÚ_«V­Zµjýx½÷îÝ»wï³ÖøÓ(êu{óæÍ›7o~ýu“Ƈ>|ø4hРAƒL0ÖÔÔÔÔÔd‚÷7nܸìÚµk×®]€»$sä€ëëk qjâÔÄ©@lDlDlÙ.²]d; 4 4 4>|4ø(ðìÖ³[Ïn[’·$oI²çeÏËž÷EýÁF0€h_ü¿/ú¢/{i3Öf¬ÍX òåÊ—+_ìíìíìíëUÖ«¬WfÙfÙfÙ€ñãÆ½ûz÷õî54jhÔ” ” ” ™í2Ûe¶—ôUáp8‡ÃùóhݺuëÖ­™Z¦L™2e¾HÚNÿŒŒŒŒŒüþãp~-E½n³fÍš5k0~üøñãÇ—t« &L˜0öîÝ»wï^ k×®]»vdddddd€¼¼¼¼¼<`ýúõëׯgIáGŽ9räH&ô·oß¾}û6‹$ÿU”Ôq9çO… ß§Ø…,dh¿Ó~§ýІ6´X–j¢&j@5TCµ/v”°…!@2ïfÞͼ ¤ôMé›ÒˆŠŠ¢œ¢œ¢œ€ðÍá›Ã7oåßÊ¿•^Œz1êÅ(à~ûûíï·59ÔäP{±{ÿ¥á”-õTw¨îPÝ8ú;ú;ú´*hUÐÊy”ó(çX†Y†Y†&mMÚš´J(u¢Ô @ÛDÛDÛP¯:_u> ÐM¡›B·’¾*‡Ãáp8¿555555ÀÆÆÆÆÆ¦¤[ÃùÕPDûïÙNV9­ZµjÕªЭ[·nݾ2>—“““““cB7íwôèÑ£G²•…YŸp8ç÷B¶¤Àáp8’È´‘i#ÓPõRõRõŒÌÌ̇®]ºÍlšÙ4³ú{÷÷îï ,˜·`Þ‚yÀQã†G ÐÆ¡C”Á€¶‰;w&îB;…v í48w(îP°äù’çKžnönönö@~“ü&ùM€=vôØÑÿbü‹ñ/€Ž3:f5Ô8Pã`‘e‘e‘ÅÅîŠÝ»³ëMÖ›¬7®Ë\—¹.¦ÅM‹›l;¾íø¶ãÀÅð‹áÃS_L}1ˆ™3=f:•• b<‡Ãáp8œï¤jÕªU«VêÕ«W¯Þ¿x×R¤+cnÞ¼yóæÍ‚åÞ¿ÿþý{VŽ,"ÈŠþO+V¬X±bàìììììÌê©]»víÚµ oEºRyÀ‚YSüê VÔ?d¥AÂÙ²eË–- ìÞ½{÷îÝE¯/44444èÞ½{÷îÝ]]]]]]v¾ÔOÒë:tèСCjÕªU«V 8qâĉ'GGGGGG@YYYYY033333,X°`Á‚‚õ|ëu#áX]]]]ý ë®I“&Mš4 •••••e$Ò c÷ÑÚµk×®]ûíׇ„ꈈˆˆˆ ?????¿ðýæÍ›7oÞ<&|:tèСóh'AœÚ9}úôéÓ§³òt?RûœœœœœUUUUUU¶¥Ï'}~$ùÖãšššššš²ûHIIIIII¬:oI(ÒŸ¼ïK—.]ºtiv_Ò}µ}ûöíÛ·ûuâp8œŸøæp8ÿ´Ý´Ý´ÝØÖ°P5Pô¡}/ð/¾Ø1©øÂ›’éÔµ©kS×ñyñyñy@Ô¨!QC€ðÇáÃok¿­ý¶6ðrçË/wÕ«?VŽ”:RêH©"4x>æc>{©¬¡¬¡¬8¾q|ãø¨Ø´bÓŠMÛƒ¶m–––€©—©—©P*ºTt©h@»£vG펀Ú9µsjç… ;v”ôÕàp8‡ó+iÙ²eË–-™pFV $¼äiL\¿~ýúõë@:uêÔ©ÃþO±$˜µhÑ¢E‹÷':vìØ±cG–‘’_._¾|ùòåLH•$+++++‹Õß©S§N:......L(œnܸqãÆ±d­t=ûõëׯ_?6ñѹsçÎ;»8§¨pá›Ãáp¾UcUcUc@užê<Õy€! a <Ê£<Àub&`¯‡`†yyy@šašaš!™™ Ä:Ç:Ç:>|BÍCÍCÍ`ï`ï`oàÙ¹gçžv>ÝùtçS S6S6óßÖïÂ!úâµüàX\¶¸lq¨l_Ù¾²=P~UùUåW6¹6¹6¹€Ù@³fãÆŒzµôjéÕ4·kn×ܨŽU«:€&4¡YÒW…ÃápŠÎ¥fWÒoXs½|¬hÔ¹QcuµçÀ|Ï™W~¸úï&U3õYÚ G!·mŽ7 ¯ó^'‡½¿|âÚ ¾æÀùúW»-VÙéSÒ½ÉùS atáÂ… .dÉüš7oÞ¼ys >>>>>xöìÙ³gÏXÄ(%)$a™ á›"Š)I 4ÌÍÍÍÍÍYÄ+ABoÍš5kÖ¬Yp?ò^ž?þüùóYD:1bĈ#F0á™"t¶ðMB$ |ù-)lSD´dÄ´$±› <|øðáÇ,²Vò|ëׯ_¿~}&@¾xñâÅ‹ë%ÁÚßßßßß¿`;êÖ­[·n]àìÙ³gÏž-èý½×Mж³³³³³+ºðM ¥J•*Uª(#ÐDDZZZZZóð¾zõêÕ«WÙÄ ÜmÚ´iÓ¦ 0hРAƒVVVVVVσVЄY©¹¹¹¹¹¹,bž&vìØ±cÇWPèsH‘ß$h“WzQ[ܼzõêÕ«WÀ“'Ož(ÜP=®®¤Þ°©fª| à:©×z÷À`‘¦Ñ?îßJÖÍÌË™s{÷)ïyܳ¿yúz Ù1±Gâ'@§¥þhýx ÆôzÖ íNt)Ó­  pUqª¢¿ôz#ßû„]L³Í'Y4)é³,œ´½©æ)7€Ñ½Ýv׺ êWvàv åº3\ÿ¢ñ%¾9§„K•K•K´ -°­9Ìa :ª£zQ*ú'¹hfÛ̶™mÔ;©wRïñUã«ÆW¢6GmŽÚ „+„+„+ïF¿ýn4ðrôËÑ/G?nü¸1pl展ÇV~Qï",¢9®¼à(**NZNZNZ@…)¦T˜” /^.°lcÙÆ² `zÒô¤éI T™ReJ•tê,ÔY¨%ª%ª% ñ ñ ñ%}U8Îß!;²v]®5¸é¤ Õº·ë¡à¡5¶íð €f²f¡¿®=¯íÞ¶±š»˜tϸÁ¨‰jÐùÂ*àµíÛ†!ªÀµ·ÆÍ|ÇÂΊØÖÐÐÐÐÐ._¾|ùòe&¸‘ÀMÖ 0`°zõêÕ«W´»xñâÅ‹áÇ>üç·¿OŸ>}úô)ø:ŸòåË—/_ˆŽŽŽŽŽþyí A“οwïÞ½{÷–ÉÝ®]»víÚP êO:i""Æi+íz.[¶lÙ²eÌz†„j‚„]ºÎ’PD5E ÇÄÄÄÄÄü¼þ£Èoš8 Hwšh îß¿ÿþ}`Û¶mÛ¶mûþãQäüš5kÖ¬YxxxxxxGŽ9rä›À¡Ïƒ·····7¬É¢ä['R(2›,Vè¾)¬ …jµêiò€NUQð~TñNîíº@@êÁƒûó€í†k Vž¶ê¯zº oÐÒà «÷|ø‰ÖÇœÙmÆ-\öï•ôÙNnDNßœÆÀýò7×ÝPöiÑ¡UxI·ªøáÂ7‡Ãáü%¨œR9¥r P T”B)”`{ØYpöaßW*XXä†å†å†éWÒ¯¤_’Œ“Œ“Œ¸9qsâæ>}øôáÚ9´shgàõ¥×—^_ž•{VîY9`OÇ=÷tÒµÓµÓµñÿy¡È@2€Ù³f€*îUÜ«¸åo•¿Uþ`ãhãhã˜m2Ûd¶ 0–5–5–ôGéÒh>×|®ùPuWuWuà ox—ôUáp8¿j»3€ gžºîë8Ðù°¯Çá)Ç_{žyÌ Œ¾±n¿°]oʾ«’|0ý¸:J@ 4(é¾âü}HV’ÑdQB‘¼$hÍž={öìÙÀóçÏŸ?μ…)BügGœ’µ¦¦¦¦æ¿¬0#Ë–OŸ>}úôé絇„èÌÌÌÌÌÌ¢[LP¤3õAV‰‰‰‰‰‰À… .\¸À"|‹ yfK ß4‘Aý( º?ÈZægAÂ÷Ì™3gΜɬj(ò{ß¾}ûöícÞÜ)]\ÐʀѣG=šm)ÒþÔ©S§Nb‘ÖùM‘ÌåÊ•+W®\ÑG3ä±NÖ4/_¾|ùò% ÄÅÅÅÅűýŠêEþ³¡ ²¨!¯v²ˆ¡ó£‰š"Orη!ôl…ÒÀ˜ÊîB5Àã×’®^zßæ9ÒzpÒp,@½‰Æ{M#M„NÀ«#O×=yÌòë7ò°°¶g߉k…Å©ŠÇ€N&½ÇõyVÒgWò,ɹtj- ºcdƒˆÆÀ⺾Ÿ·mZLqQí¸y*³H&Èo—_;¿°Ïw6O¼Õ=ã&-ÖñЛ°Xrb+ü¾¨÷Iü=Ç»!@ÖÌËÞ´ð ßÞœŸ ¾9‡ó?È[È[È[ZZZ_D¢·0oaÞ¨†j¨V”Š(ýPæ¡ÌC@ª*¤ @ÂЄ¡ C¨ÇQ£u"êDÔÞú¿õ뼌yó2x"óDæ‰ p<ãxÆñ 7p78ÀÿrÜ"Õå÷Éï“ß85wjîÔ¨x¸âኇr†å Ë–^–^–^€iŒiŒi Pʵ”k)W@ç¼Îy󀚚š  XO±žb½¢œ0‡ÃùÝ9Ö!àÀÙ!@¦jæå,m`xÝ–}ú×>ÜzÇØñ~wÆÀ`ô…[êŽÃù-!ÁŠ,2ÒÓÓÓÓÓ™õE(“… ¢äõM¿::::::E·ºø^(Òôw"¨‰¢ ÅÒ’nJ œäMcQ±´´´´´,¼½% MÐ}#iyB¯Ér„<¤¿²òñóóóóócB»‰‰‰‰‰IÁò±LB;y~ÓP@@@@@@Ñ…oºÞ$Sò×5jÔ¨QƒM0‘EEúW®\¹råÊ¿îz‰NÐõ!¯uš° ‰Ú>|øðáÃÌ’‡"í9Eã”ÅGûöwŽ_3¿ÚT}ܽ‰'€‘òSÍg4Ðý 4ÿ»Ž»Tš lÝv¬}À~ s¹†þu\€åg5Ÿ 4éÜ£ý'@ó‘öýolÔ_Ä­:—Ë.ê¦6ÝÒ|%вU_×çž"þËœ^²ž²·dƒï`0€Û•.7 ô.• È=i ä4È^íV¸õ ç÷@öÇ«àp8G:*T:©tJu.Õ¹TgÀî“Ý'»O@c“Æ&M÷÷îïÝßsêÏ©?§>pÀñ€ãG ø|ðùàóìÁ!O/O/OH6M6M6Þ?üýpàžå=Ë{–À±ÆÇk ¬¸»âÀà­ƒ·ÞÊ"á÷ßÝwÿ]`ò‹É/&¿ºtëÒ­K7 öèÚ£k¬M­M­MÝ~ºýtûJõ•ê+ÕgŒfÊfÊfÊ€ófçÍΛõë=Ö¾y¾y¾yÀ¹{çî»<“&ÿLˆÚµ;j7~4ýhúQLšÊáp~9»Ý¸](e)-T²jU}X¥)ÐîxË9Íâ€Ûuîº?ÐÞ”{×0DUz=½÷ >6z,`üÉö”c<4ŸÖoÓÒ hØÁ´{ûÿÊñë·nŽÚt_Ýï‹HÌ:wš_u±êßjµ¶ãKéõÕ¾çò •WÍ1Ú`Ó°Œ¬T¯Öc`‰ÇªØ ãAFÐLÀá`^ß999999LÐ{üøñãÇ™w4EP“ç0 ßçÎ;wî‹ðüÝ„éŸ YMŒIzØ3f̘1ìû€ê¡Èxê÷¢ ë‘Cv.Û^P S+­6èaŒÂø"|¿äù=Ôk²—§ú"¥jòà‚÷IëUY¹øÆ±÷bë•+hiû}·½ÙÒ÷¼B¯ V=ó&Æ^@Cÿrë,U€9mÆ/Á<¡ ãÀèí··v\WÔ{Wó PÕ¼´Ÿþe ÙšŠÖåÎ>ö3¶Omd¦f<ÍXQpÉö²8øpÿ>`¶Ç¸£’X»ª_7^j70تS¾Ë ´Ùk×¥¥·KñªÒTE ÚúC…Èé,¾0Fn'V>Úù|Ï÷óØÊîzÈ~}×ù®Žd‚8µ{ÍÀïç^eå…Š‚ž ìÍØ"ë; è6«ÉðúKëË 3ÜȶÝ;5íÖ`³P)Œ Ð«òWFý\ÜÛ<jiYT.=hz¥B Û[¬ß’|¼â¿ý¾<å| |_PYÖ@VK˜)Œ~:ÂÏï¾9‡óG ûIö“ì'@3B3B30[k¶Öl-P5¤jHÕ ý¥ö—Ú_ÆTSmL5`mãµ×6.¸üáò Å2Å2Å’ é™ê™ê™ê@l£ØF±€—ï^¾{ùŒ Œ Œü:ùuòëxUðªàU¨=¸öàÚƒ·3ÞÎx;X<|ñðÅÃÁòƒåË-«·¬Þ²:P1¯b^Å< t¯Ò½J÷Ô;ªwTïÈ8È8È8rörörö@u¿ê~Õý€þóûÏï?XôhÑ£E€óÌ?0¸åËÿ–?âââ$š$š$š9Ú9Ú9Ú%}58œ?‹DÝDí¤Xà\ËKVWÆÍÏ5þT? øYqbcÀåhÛ.-6±òÛûí:x HI~ŒŽ‡ÚÕl=˜5cJ¿ ­Ùÿ—Y°Ôë°tÜü3¿2ZÏRΚò9hq±c^Ï[€ÝKÛÖ€——§×8/@?N÷‰nà±Ä«ÜüƒÀö»Îï/F«ÎŸ óœ¦d—$œÖ®]»víÚ¬|ƒ 4hÀ¬Q(’¶uëÖ­[·þöãK å$Àÿ)Pû)Iä¡C‡:ļª%! J(­>²Œ!ïpi^ÉdÉA‚é°aÆ Æ"óöy?zݺuëÖ­[7vß‘J0­<ø^heMTPòPò²—M(¹d}’ýA®dD?YÑ--[¶lÙ²…½–&v\ÂØØØØØ˜MhI«OZ²M‚&¼HÐ>vìØ±cÇ –£ déCÉ7ÿ´ ™’"7"·onàéÊj÷¯•ôª>¬n¨þ#€+zµ¬ßú‹•·5®” œ&½¼ýŒSšòev(»œË<,0[ßwpµÍù-g_ÃFu=Þ©tÁxõÊùisó®Lrw°©.&ÝôtY`»x5ÐjhÇágûnoMôŒüÐÓ³K- ß[´‘ÆBuOLZ$W“Oz_Û¸gËR`ŽÌªŠëb€7å^ŒÖ ·§oj¯™(pîÞ-³Gàuççóž ¼riÛæ6púÆá}—Éî‰#>ܯ¬’½_ùã@ý€æZÚ³H&yMñšµmw§ýe@¾ŒüvùKÀºÕûÚÚ´/ß=²çVXë,^³p°°¶§ÞÄ5b½Çöbÿ õëK‘Kj‘L´èÖýÑ/ôxÈW~?q:æ”:0$½sœËB m_ŠyÊ `D¦g‹iÝD‹›¾ÏØù:ÓsP7‡Âûûÿï›’ªÎF?n4oë|Çå20kÑŠÁ«µ™§2ñ2À InuÂáp8œÿ$ʩʩʩ€2”¡ À0`;ØÀAÄÁ¯ì¸ «°Š½Ì×È×È×Ò¥-J[$ÏKž—<ˆû÷)îð¡Ë‡.ºa—Â.…]^½6zmJþèïïïïï²4Q}¯nªÞˆ=¥ø±?€º_/_º‹™¯Yo`q_­m†€Ì.™×2k”ƒ€¹»V×_¿ZºK³ŽqÀ…'«o4‡3\D*ŠI"·4]9pYM ß©QcÒ±ugŽž“ûÏqj@õŽÖFéu§›pAóDÏcÝž.øÚ<}™{–ý-«Kl ßéÈ<•¹&cÃÞO>”Ø#q°°¶§ÎÄ5Àë¬nÏÛ¶Áå—;ìbåFÞ™RuF[ S5íDú|`Ÿï¶·›õ€û½nÙÞœÑòdPV±¼ŸÃq ~dóÉ-jJ‹²i¶ù$‹&¬>²˜)ma6ÕÜñ5õêj5ÙÒ¬@[òNå9çUü… ÖYMv·qo÷˜ç°6mƒ8Îø'‘qí,/ºWlª×@¸,fBÀm 7†µùE¿,É™¹lZ- ¬RùÒÿ‹gL/>]•†( ` &`rËÜÛ<˜Ya”ãðÀ½ò7Þ\wlƒ–ÍAôåÛ'—/Æþ³ ¦{ƒ¼F«€…;7îÙ’È&‰V0 \øæp8çM•M•M4¡ MšÃ5‡kÊ  Êp‚œŠRÑ?žèY#²FdR‡¥K$}€°Ô°Ô°Tàuï×½_÷žx~àùàxåã•Wv,Ù±dÇ’/ê÷ƒßÿ¤1—ä!ݸ¥qKã–@•¼*yUò€òCÊ)?(û°ìòóÚæµÍk¥w–ÞYz' ¯¦¯¦¯hNÔœ¨9P/¯^^½|I_ ΟÎG“¨ Ñ¡Àµ7}ƒfõ®ÕžXc+ ÷I÷±NXÁò9×l=؇Ã8`{ÿ]÷Wšá÷¾É£\CAŒP—†j†ê0•$à“~|¥Dñ:€ ß‚"u¥Y%$àR„iaP(­^²> ÈPÚJ²aÆ 6°maP¤ôB‘Õ…õ AgÏž={ö¬ôr[L‚ì÷ò­ý'Mh%ŠzÝH0.jRÃ÷ïß¿ÿžEÄS¤{qC’–"ß E¬“÷µ4H`&Á¹0(òûGK‘Ö´’€¶ÒfÕCPRP¼5YŠYŠYŠ@×n]»uíx{{µ÷×Þ_{? &&öëÛU\è–ªf(zg€„³ñ«?‰+,z~O}ä5R/©y’Pee KÃ3úã¾ò=nRÎÜÛ¼`ø¿Õk¨R:ºôJàãΈéï•tÁmˆ¨º5ô.À&LíÚû!`ÞÞØ (…Ô¾þ¾ÖÃ’rJùn/#¿]á€Wh yÞyµóŠ`åaô®ô3“y@Ï9ƒ0@O ÂPw G&gBŽ pÍáÜ–³†€OàŒíSn³<ÆNåT‰©WK°0´1(û V>ªÇÕ•Ô»Wvq:¸ÚæÜ‚3@HÓ׺ÁÆÿÚÏÆûÇŸdûå÷Ê·ÍÿÂZ&ºã‡†‘_¬À*³ÍÒÅÊ@Ä×KÖ,åQÿ,0@¦OÆÓ/…oòz—Õ“õ“ Ò•R—¤žâõãrc+¥Q¦³YÑO÷· ߇Ãáü…È7–o,ßÐHÑHÑH4  |‰¾Ìi™Ó²¯ìØ hY€ÿÒsæçÌÏ™$‡%‡%‡ J J J@ô¸èqÑ〈àˆàˆ`à]ÓwMß5^|uðÕAà‰Áƒ'Àé–§[ž.Ê’øm؆¯~ ü„ههÙoV½Yõfð<çyÎóàTƒS N5ü¶ùmóÛ 1ˆÐMÐä+ w„#¾ðN7h8Ðp P¥j•ªUª¾¾¾@Y…² eóÑæ£ÍG¥_–~Yú% ßH¿‘~#@k¿Ö~­ý€úFõêKújpŠÊî^\¬d—È>•- Ìž6µÉ]Q8–Ë”¾_ÀÕsƒ.Í®«Üò¾3Ø?àHßepGò¹ò×äVYÊŸÏ}ž@t —J´q̈إ€Q´áZƒ%Ý+ç§p·qH4:i4»#wGî oDÞˆ¼@n£ÜF¹€\£\£\# 7#7#7È}—û.÷””ä\̹˜sÈ=“{&÷ {.÷\î9 ÷FîÜ@npnpn0“˜“˜“äjäjäjyUòªäUr{æöÌí ä-Ê[”·ˆ­Ëûœ÷9ï3_+¿V~- oZÞ´¼i@þõüëù×|­|­|- ß=ß=ß ‡…À +È ²€ÐMè&tË¢%(p‡;Ü™2'dN2Ê2Ê2Ê€Œ›Œ›Œ {Pö ìA ¿Q~£üFÀ¤œI9“r€ô³égÓÏrÚrÚrÚ€]„]„]phÞ¡y‡æò³ägÉÏäË–; È¿’%ÿ ϑϑÏäääy'y'y'@¡©BS…¦€|;ùvòí¾Ø¶”o)ßP¨£PG¡ o+o+o ȫʫʫòQòQòQ€üù+òW¹Ur«äVr=äzÈõ4b5b5b9;9;9»’¾Éþ»¤žO=Ÿz@TA•‚ï¶m5Ú Ñ  K^—¼.yÀÜÞs{Ïí ”«P®B¹ d! Ùo;ö¯¤Ýñ.fÝÚKz)LwNìÞ¯´çÐݾ)ô{k©UÑ˘`Þji‡k®¤DëGV ÛzÀ!8â+É@r´Å航aá¡õ*÷j®«U@CQF7:brµŒcT€¼S¹ír«6KìÖÙ¬„à“Óögì½”óª8´’€`.Å߯ɎbRÌCz~®Ûkv#+ ­ä t­Ù¯lQr‡êLÒ›­—ýEû{æÛæ›Ø^´ãßÏ»å³"`qðáþç€ûöáƒF™g§Ï­gl.8€ 2ô½O5ì+·Ñ;“ç¦ó¾¸~ÿx¬˜ŒËSòÔé G¨i´=!Þgᄪ_Xœu¹Ü§m¿s@e§j®5´€¾ÍGž# l±tãâd p²˜L³1Z¶M+þëô³àÂ7‡Ãáp8œ_†\]¹ºruºu5ê²HtS˜Â€cmÇÚŽµ¿Ø¡#:~Õì¯/ú¢/ðyê穟§©SS§¦Në%ÖK¬DïŽÞ½ˆÐŠÐŠÐB;ó‚¸:IÀ¨}-šJ.Oî‰Üaö:G!§].Å<͇óG x‚2&eLÊ ×)×)× È^™½2{%””|výìúÙø|þóùÏç,«,«,+ kIÖ’¬%@¦l¦l¦,1!cBÆ #:#:#È–1,c›› ¤H‘6HKMKMKR}R}R}€4Ó4Ó4S åxÊñ”ã@jÇÔŽ©¤ @ò¾ä}Éû€”î)ÝSºÉêÉêÉêì8ÅFy”Ç—–]D`ö£¤!…¡­¯F>>Á“ÿY["E(,ðûFÃ1ûÊÿwb'v~åÿ±_›ž…Y˜Uøiä"¹F<ñ|ÄsGqT4{ø¸|“Fí”ÖÞxÿ²?YÈIZÉý ZêZêZê€–š–š– yIó’æ%@k˜Ö0­a€fÍ2šeÍ@Í@Í@@£«FW®€FŒFŒF  >G}Žú@]M]M] P_¢¾D}  ¦®¦®¦¨-Q[¢¶PÍWÍWÍTF©ŒR¨¼Wy¯òPn©ÜR¹% ¼OyŸò>@ISISIP¡8Bq xMñšâ5@ÁLÁLÁ ÐòÔòÔòd¢d¢d¢Š¯¾—ä€ä€ä€¢—?°äÀ’KØÖh˜Ñ0£aÀúGë­´éÞ¦{›î€âhÅÑŠ£Kúì=BÆ ñ6ó³Û® ,2Ya‚ £©»E¯;P? ù€–ö÷#asÙ¯!ÓÍ€›;\<ôŠ||XÚ?‘¼Û¥÷h•ÝMü3¾F3PªÜYù +#>þCýt¬›™u2çM*´©Ûn €†âûõ#Ä$+1^W€-ÍVæ,·VUô×Û^Лû숣sO¦¯é5t)à¹w¡Þâ€íÑò_M¶ø£ÔÙØøZÓ€niý^úaÀê ÞÏ­Ø<´(o89ÖS;¬à~d³NË{Ï|_@k8µ76¾ÖT4…„〜‡ÜMÙ` ¯_îæÜH@X ûtÞÉî‰#>³z‚ª˜:v¾ Îù’#>þÃüt‹ / ×9·Wñ}« ¶ å>ÆsL—“Û3{W,Ð%¢OßþM˜—9qùÉ™ùÀé‡C.Ú=éÚ¯»èá÷¯)„\£8þ pLuw´ÿJ`ѱ©7=Fµ ½l¢ (×Qi¤2ã'\°b† ߇ÃápþX”(-PZÀÏôé?Ò”EY”ý² ?üáÿ• ¦` ¦°—©™©™©™@ŠUŠUŠ·$nIÜàcÚÇ´i@˜{˜{˜;ðææ››onÏ«<¯ò¼ pvãÙg7þÓü§ù™Ü«&jâ_–@6ùç½öà#{zlrÌÀ\1¶ià&wÃîZmÿÚ7j¬®ú¨ô´Â»òfÀÍ*AÓïµÞY…. ; tÕèxÝù °+°@«s®¡n+€ÓÜm»O¢bFÄ-¶ïݸ¿:`ûÑæ¸Õk‘øjÊ6ýOzOtÃØë ˧už“¸ÌhÛ¬…þ?‚ý§’îUί"51515ø¬úYõ³*u:ëtÖi sRæ¤ÌI@º[º[ºÖ#­GZ ­wZï´Þ@ŠgŠgŠ'ò*åUÊ+ Ù:Ù:ÙHž“<'yd‘d‘d$=Iz’ôHœ™83q&X?±~b} 1?1?1HìØ!±¿/~_ü> Û1Û1ÛñN`1ã ÁÝÑÝ¿x=CQ¯kÀø—÷WaV±— gÎ(œ´ëi×Ó®h)k)k)Zó´æiÍ4 5 5 ãÆê¯Õ_«¿4*jTÔ¨¨­U[«¶Pû¨öQí# ê¢ê¢ê¨žW=¯zPqPqPqTÖ¨¬QY(«)«)«}ñ;¤ ¤ ¤(-VZ¬´PÔUÔUÔ}}}{{{Y¬à¦à¦àÈçÊçÊçr~r~r~,RY.G.G.="{Dö 7Xn°Ü`@ÖZÖZÖÐòÑòÑò)黵äH¶K¶K¶òç=Î{ ä/Î_œ¿Èk’×$¯ —ž—ž—äíÈÛ‘·Èm“Û&· û)÷Sî' ×'×'×ȱɱɱ²OfŸÌ> ä4Ìi˜Óø|ûóíÏ·lçlçlgàóýÏ÷?ß²ZgµÎj d]ʺ”u È´Ë´Ë´2Öe¬ËXdB†d É’1HJJÒ Ò Ò €ÔI©“R'©ËR—¥.RZ¥´JiD‹9 H>ž|<ù8”Ÿ”Ÿ”¤ôKé—ÒÀìùz<)øÀ_Þû±û¿RŽ"ø¥AIÐ AÁJÁJÁ Ћ׋׋tê6Ômèxëxëxºt7ènt‚t‚t‚íëÚ×µ¯:î:î:î€Ö&­MZ›íñÚãµÇš.š.š.€æ#ÍGš€‡¡C†~ÿý½>z}ôú/â)nán“OO>=ù40.a\¸@ei>Ó¿òb^³lwÃý€aÝŽwꌬÖÓ³ë  Êùš5s€ò•+;>oÌ:˜9¸9$pÀ¥š@ÔÈöë€æfΧ]Ncôg„Í:Yøqc7G§Duú(µókyèè׳iïÑÀû ï^½MvwðµÛ°h˜Ø²~ë‹@7íÍö/«dïWþ8ÐeU_çþ€£·ÝÚ Z¿Ë«ŽS€æmï¸\b2>ìTÜppm`{Ðaz… @£žMzÇüü~]0d}}ßuÀ¨”^æÝVýú:/håØÛTºYy`yÁ6±ÜG §ÁçŸÝ€û!·_Üœ$èÅ-«ô‹m46(eïWþ ÉX{’îl½l b~íürÀ¸^}åzEmê‹I%«Ê×ÞWWP=®ÞA½+°âÑœŠ^™@ú‡´åiµêJê]+玞‰n4º8àÂQ@e¦Ziµ@º_Úç4ú=lÀ"ù'„Ïi=ߘø¶ÿ%÷S@?'燭­ç]ßtï$|ü´;Îð«ºîéC fjƒôF󺵛Ø5ë $WIì‘ð/ãK¶Ç÷™½nÞÀcæ`¯þë€MË—¦,~ŒÆôÏ^?ï²2‚PÔ´‡Ãáp8œ¢ðyÊç)Ÿ§iÊiÊiÊ@¸„q 〘71obÞ!“îݸwHé4n̸1@ÿ{¯½”·X^²P/éÖÿù”]ãd£·@¢n’LòC Òè¥÷½«€\®Ü5¹ÕE¯góY»/C65öè+ У>s§N¯:9ØÓë`Ç£«€¹^‹¬h„Z½O˜ؽ´Ýisðž<+sÊbÀß}ßØÃ·h£Ø±KóFî•cÇd-Áèï7bÐøh`·#'ËæaeLN/lï´»l Û4.gŠ=àï¾ì¡ UùÃÚ×ÿÚ<°ƒi÷¼’[Z+^ 8^ÒWçïeõÓZšLn_KùºȽ_×¾Þdà£ßG¿~@d…È ‘€ðsáçÂÏ0‚Œ~]ûä,ä,ä,}g}g}g@/R/R/Й¯3_g> ã¢ã¢ãh­ÖZ­µÐzªõTë) ©¯©¯©h¸i¸i¸¾¾¾€z„z„z VQ­¢ZE@m¬ÚXµ±€ÊE•‹*@¥“J'•N€Ò.¥]J»¥t¥t¥t@©¥RK¥–€ÂV…­ [… … … @¾½|{ùö€Zµ&jMÙ»²weï–ôÕåpþ,’7&oLÞäÔÊ©•S ÈY”³(gœœ |¶ülùÙÈž5a½Òú½ €ú-´´FÞ™â4£  ÓRo´^¼ôöï3kãÜp Ïø®£¿²Òå^·w®·¼êжím`Ýê}ííê6h²¥Y‡‚åCK½É­l¿°æêÊ|àαkIWûŸÇÞ‹© (^SœªäØu¬Ô¥ÒL »ê€üÁóÙ„BþÔ‹;W +ënÔ3x¡úøñÃÍ€‹C÷ÈžÖÀÌ€eSW•î犖'Ë'Îê4Cxóù¥ûóö€r]•Æ*3€úÍ&·¬Œ¼3µêô6ÀìÖ㌎âFÇ„F·f]q»Ù®àñ¯þ#˜o,·¤×â!ÀkÛãžõtZéÒšîj›ìüZìïémµùi­€$Ÿ¯xE ¡¹uV*…÷s¿¾ÎóZ%Oï›Ý{ ÌÛc[VÖöZŸD…Æ'm†Œ™0wó'àJãm—ÆÚæÛŒ³u¿â Ä…o‡Ãáp8œ_L–É[¼´»¬LY úv.|s8:nòöõªêûJGŽÝ ˜+X.´\˜*›*›*ÆOŒŸ?ŒŽ3:”š_j~©ù€Þ$½Iz“Ý¥ºKu—ZG´Žh4ïkÞ×¼¨›«›«›jóÕæ«ÍT>ª|Tù(Q£4P©£RG¥ b¦b¦bVÒ½Àáp8?ÎçÖŸ[n dçeçeç‹ ,2æïž¿{þîŸüÊg[>ðð3ò7^¦]Ò½Qü|«°ÌáüN|«ðÍ­N8‡Ãáp8ç™ll¡c> ˜ÜÓz²M2Peñõ¤_[šßÑù‹-Ñ=ÿ'{™Ìð¥}‡p¨¤Ï’Ãáp~>J§•N+fVv©^©^©Åé©0s1±`Ä‚ €¾¶}mûÚs'ùÞíä´B¢l€G´Kº78ÎÀ…o‡Ãáp8‡Ãáp8ÎoIô£èGѾ}?§×N¯^£ŸŽ~:ú)Ðr^Ëy-çFÖFÖFÖ2 V^Îb÷àGM€äzæµ(鳿p8ž9‡Ãáp8‡Ãáp8¿%Ñ¢D?(ø`ø¡á‡†úF÷î T°5çô¬¸àÍù[áÂ7‡Ãáp8‡Ãáüá‚ pìØ±cÇŽ'Nœ8qâðáÇ>êêêêêê@õêÕ«W¯ôéÓ§OŸ>€‘‘‘‘‘QI·þç3pàÀZZZZZZÀÒ¥K—.]úíõœ9sæÌ™3€·····wáå====== nݺuëÖ 4hÐ @IIIII©¤{‡ó_áùóçÏŸ?víÚµk×.öš°±±±±±ÜÜÜÜÜÜGGGGGÇÂë¥Ï}>¤AÚ******€±±±±±1Ю]»víÚ;vìØ±cÁýZToQ½Eu×p ×Jº9Ο„lI7€Ãáp8‡ó{ØôêÇòÀ¨u“§_Úéz¼OC ã‰^ƒœ¼§-·]|2ˆoP¯¤[Ëù¯’/+˜ 5€póˆçÚ•tkJžÜÜÜÜÜ\ÀÙÙÙÙÙ™ G»wïÞ½{7ðæÍ›7oÞ€§§§§§'`ggggg\¹råÊ•+%}?Ÿ{÷îÝ»wxüøñãÇ¿¿žèèèèèhÖoÉÉÉÉÉÉ€¼¼¼¼¼|Ámzzzzz:pöìÙ³gÏ£F5jЬY³fÍš±ëÇáü hBlÚ´iÓ¦M*UªT©R%`áÂ… .dÂ÷Ë—/_¾| ¬ZµjÕªU€“““““Я_¿~ýúÙÙÙÙÙÙÒóêÕ«W¯^±Ï…¬¬¬¬¬lÁσœœœœœþ§\]]]]])S¦L™2¥¤{í¿‡PQÐ4€KòN^OÆ\¡ ÛÔõ†ëH`ÂÔ~¡½[K­Š^aÄ7޽[·¤[ýóÙu`SûõG€á£ºïÔ§¤[Ãù^¸ðÍáp8‡ó%A/Ñ}ñ¼40Í{NÜ¢†€ý›ê'¾V}œö¬ã·ƒÃ) ¹ ¹ír½7[-èxØÓëP“£“KºU%ÏæÍ›7oÞ œ:uêÔ©SÀ¤I“&Mš$$$$$$ïÞ½{÷î\¾|ùòåËL˜êÙ³gÏž=œœœœœœ’>›?/\¸páÂ…‚Û7nܸqˆŒŒŒŒŒ:uêÔ©S'àúõëׯ_Ž9räÈ‘’> ÎßÊìÙ³gÏž ,X°`Á‚@óæÍ›7o¼}ûöíÛ·lûúõëׯ_áááááá@¯^½zõêlß¾}ûöíL/*Ò?÷ïß¿ÿ>›˜+[¶lÙ²e *****ª¤{ïï'ïTžs^5`Ô™^ƒº9ãdûõÌR]8°x¿<䯻Àù×ß]ë ¬4ž[Ñ+hߢVùªZÀ½ò7OߨSÒgñó_öîÆ»Àƒ‡·WÜ´(éÖp¾.|s8‡ÃáüƒÛ`·ÁnƒÙRÜj[«m­¶Xùiå§•Ÿ€W5^ÕxUø|úóéϧKºµßO¾\~Å|W í™.Çû4.7¾vûÖ`éØù›gFŸ´C´žF*]½q65}rýveàB£cÏ÷F¹òyõòFmÏt=îÞHÔMÔNŠ-é³âüí|Vú<<;¸U÷Ψû%ݚ߇óçÏŸ?ÐÔÔÔÔÔ-Z´hÑ"f% IÆ 6l̘1cÆŒÀÇ?~ü\½zõêÕ«%}6/ªªªªªªÀœ9sæÌ™ÃþÏûó3 æÍ›7oÞ< Aƒ 4`dÖÖÖÖÖÖ÷#ë K—.]ºta‘Ù—.]ºtéRñµÓÔÔÔÔÔ;vìØ±c¼¼¼¼¼<àæÍ›7oÞ,é^üû9|vç´æÀµ6ç·œ} ôm>²áYàú³·UÂ/ïM~|¸&ó¦YØ;`KÎ1¿@f—l°ìGÀsø‘ýg¹¹}s›”ôÙ?Ã\=FN¼sµõ­†%ÝÎ÷Â…o‡Ãáp8œзӷӷc¯ï¸?àþ`¬ÁXƒ±€ý]û»öwå6Êm”ÛæûÍ÷›ï¦c:¦¸;ñîÄ»´^i½Òz•ôÙHgË ¿×{wjÝoô0˜?e†Ç[`ìÒáå Ù »zܯñÅ¥ëæk†ù4™×ˆ1Š·Ø2hçë½ Kú¬8œÿ&ä™™™™™ ÄÆÆÆÆa"Š"½)â¸B… *T(XŽ´îÝ»wïÞÐÕÕÕÕÕeÂz½zõêիǬT¤1tèСC‡ÕªU«V­ó 'aeeeeeeÀÌÌÌÌÌŒE¨ d$ì©©©©©©±Rì~H'h¢U6lذa»>t½MLLLLL€ñãÇ?žYªHãÚµk×®]cÚÚÚÚÚÚl„"oݺuëÖ­‚ûïÝ»wïÞ½¬½äå\£F5j°ëgiiiiiÉ"wÉjCd3räÈ‘#G¥K—.]º4;O:ï7nܸQz=’í»{÷îÝ»wV­ZµjÕŠyÜëèèèèè°f:¾46mÚ´iÓ& råÊ•+WfׯT©R¥J•z÷îÝ»woÑ/âú•mÛ¶mÛ¶ É4áBV#EeñâÅ‹/f¯·nݺuëÖoŸ$ßú¹à·j_.i 6_=M£0öìÌÀÙ¹€ÒPåÎÊ‹ –¯ö¢Nëº7!¯'îž¼ˆóN‰îÜϽé£Â·ÿwG{’îl½lÀ4Û|’Å_(ìÿWàÂ7‡Ãáp8Î?اۧۧ½|x·ðnáÝ€ù2óeæË5–ÖXZc) ±[c·Æn@½z;õvÀ§!NCœ€ -/´¼Ðˆ¯žÔ,©€Ð’9Ï]nú9¨¥©µQ= Œ^1tVÿöEß¿Û^×·í/ËG/œ9ë(ÐödË•M –KÑJ‰HÝÀ<ÃMbíÖW(ç• °š T|Y{aS`Ó°í¥üÓ¤o_ÃU÷äättÊ”‚jßsyÆ,ZÔ²•µŒâË^¯rðš·àð’§@ŽbN¯œÀ”ųTNfïë¦Z˜; ºì—;,Kzĺäq϶¾Øøò^ æý&‰í¦*¹†{¬Ý«ðÊkK|øpàøñãÇÚ´iÓ¦M›‚BÿÏú‡&$(©ê·baaaaaT¬X±bŊ̪¤¸ ïð-[¶lÙ²…yÓçç¢xMiª’?ðyCÖÁÌÉ@ÂÇO»?Y¾_Nͺ–çïˆÞ­ ØT³?UþrÁr‚Ã=ß&ß´ªß& ^›‡æU€ê×M§—Ú ô9ßö@ Uàî<ÑJE³üÇ™ÇÊïTÜ0imPû½¥©É  I‚Cë²Ï€» ®/½*T–5Õ’V¯œŸ6çQáçCV/-Ô+Ç”_Í<ÏÖöЛ¸¨Uϼ‰±—ôýƒB¯Ê_ ôWpqoó¨¥eQ¹ôx é• 5lo³=Æm•$ù$xÅ+J¯çÀèí··v\WÔ{Wó PÕ¼´Ÿþe ÙšŠÖåÎ>ö3¶Omd¦f<ÍXñ+î¿ù’n‡Ãáp8Îï‚u?ë~ÖýÌÄLÌüñúÒO¥ŸJ?lÂ&lÛuÿyx<×åל ²·êÜq¿¯ 4¼\·e-u@9S9MY­èõÈçÈŸ”÷Fc(Ð?«²÷3U3×gjn·óï<x^áåâ׫ákÆõy”}c}ÞR8î°ùœ0lÓ¸ÅSìp³ˆ·•€ySfØLþŠ,Z&øŒª6ø&0}ÎĆcv†o-»S ˜çåã¼²pìq@«s¦€idé}ÆŠÀΞ›Æ­ÊÞÙ„¼¿ŒYí4s  ¯SN{ °Ëô¦H?n§£½kL7¡Ë(%`WÍŸV¿η,u­+0v•ç¯À§Å •&Þ“fEOóKûå˜{`€oo“S)óÇ·i Õº·ì¡50Õ{Nœw ’©üY¹°Kñe@-Yà´¹Ò¥NïžÀÝ:=î [;à^o±}c,u˜5Έ FNM>–ŽºÌ™6­é$ÝâoŸõ[ËD‹–Àáöþû6\»uè ôÝÒ«y×£@×}ãœß²gdÈN ŠùÃóÓºuëÖ­[¾¾¾¾¾¾,x̘1cÆŒaÛ2eÊ”)ShÙ²eË–->}úôéÓ‡EšJ2}úôéÓ§3aêáÇ>d¹Äˆ#FŒÔ¯_¿~ýúÀ¸qãÆ¼xñâÅ‹ëMIIIIIaV ””“ Ž„?Šä%A”ðòòòòòb‘¼ù­¯¯¯¯¯ÏÊÑùI§¸ðóóóóócB£$‰Ä"ª©¿HÀ&h¢‚ÑÉ“'Ož<™YØHBt~‡:tèë¯Ó§OŸ>}HMMMMMe $($¸’ýèÑ£G±ûFò€–¢)Òžß%K–,Y²„YY• ötœ8pèܹsçÎ_`$0Óÿ©_ú÷ïß¿é–4!D?AïN÷—ä„õ“ »Î’Ð …+V¬X±øðáǘ…ÇÏúM\P;HPþ^HöìÙ³gÏØD›‚‚‚‚‚BÁòä-.aN‰‰‰‰‰‰l‹rL:uêÔ©¬_9?—vó»ªv¯œnt¸ïÁ&@ïR­'5k¸2g˜ÐÀ»E‡V¦#žõâ Z<šÄ·A[ñ_-¿¬7&#ÊèãÀmlËîMfòeäg*\úÔ­¨h¨VTUNß84í`5`ˆjçÇ.[€5k÷L8°¨3¢ñѦ_YyZêMþuÀ÷î²jK¸vwsèSˆÉøhüá=PµMYõ:UÎÖ0«\ð>5òxU`TÔ´˜™yëKÛ›jžr¸é8÷âZ çÑA+‡ŽdÒdȈézÿÖ8sJ—ÞG±×BÀvŸƒy…]Àˆîž†Óº©&ÉNÉO¿ë|WŸÞ*½ô{yØ‘Pû\ ë){K6˜ ô›¯¬p^zhÙ­Ã ×@ ‡ËÀCÎï—… ÷Ø{{Kâ¦iÀ«¨§ž ߣ‡N”cõp¾¾9‡ÃáüõdœÌ8™qH–:-uDµ‹jÕno¼½ñöÆ?^aØ[ÆYÆî9¡¡¿®ô-’€ÜÄÜðÜ<Àls™&¦€³(ÆÌu#77ók.6»2ò†@O¤ŸW¯]·¹v¦Î5z;€¹tXÁò<éý!.ª!°dòêCºc‡M¸0Š2\PªûÏï—Þ;ºÏéTXàáuÀsñA´ꢖ3p÷ðÃ+{{Ê8n¬ÅÒ¤ÇÙþ;ûìõ:\kxsPÐ]àÆøt”G°IDATTË ýv­šmLýœ A?ô¶L#Lªß¼Ç-7\{jÒCïÊ@éÆC,‹¯}ê©êuÕ¶ÍÔÔÿâ¼m_Û\±JZžnÓ¨;þs‚·$ÙÜ­[·nݺ±HT²¤¸xñâÅ‹Y2LÚ«cžã´Vîø°“/€ ¢õß’œ™Ë¦ÕÊ*•/í0ð¿xÆôâC@ÑUiˆÒ`6j&·Ì½Í〙F9_Ü+ãÍuW ´¢™Ù%`KÓ•—Õúå0&[wæè9¹ê ¨5Ô;Z?u¦×nÀÍ=uZxº€çš—·:áp8‡óÛ‘S;§vNm i`ÒÀ¤@hVhVh”””v;ìvØ XZai…¥€Áƒ<¨£TG©Ž ¬«¬«¬Ë¬ÔœÕœÕœ£'FOŒž‰‰‰@³Ív6Û ôïß?ØÔySçM¼ý’Ôu«ëV× xV÷YÝguÇ2çôÏéåþÚ~d-Á”½–d’e~‚PxÒùìŒ €y¨™©éF Ó•¶_‰¦ã{,›5¼ È fB àT»³c.~–^Ó Uë…ü¿~œÞUÝë€R–ÒB%[ öÍ~U“ÅÏŠë,o) ´ÑƱ#b—~^ý¶ŠÆÒè¾§Óýö»€\…Üv¹ÞÀùúW»ýº~iq¶É»†Ë¥¿ol}Õ*HÒI–I~ÈÚIíxêÜ™9€V’–¦f;ÀøÁž¬F$·UïUÉ­´†YŒ\h~YáZÝŸ×>NÑÐÐÐÐÐÐ`¹dé@I,oß¾}ûöí‚d5À"2ÉÚ€,#¤mI¨#(òUò4&!M$¨IZw`HžæÒ"~%±³³³³³+¼Ü·BB3 ‚ÔÞ+W®\¹r…E®ÆÇÇÇÇÇ3!^š`H‘¯ Â…õ?E–Kö;E‚Ó„E8;999991ᜬDîß¿ÿþýÂÏ›¼¼¥!)NV* ºQý­×/<<<<<\zyòЖ†dÿKÞg$´;888883gΜ9sfAëú¿d¿ÿìÏQaPd}\\\\\Ü·ï/ITTTTT ¥¥¥¥¥UГ[ú|Òç"+++++‹}Ï(*****2ËZ¹Â)\[¹Ís\õô]ps`Aòús¾›€¶'º˜ukäÊsέ>ã?ÝÏ軴݆–¹ÀÓ Ƽ`Ö ´ |ræE@>P>¨Š©c7ÑB%ΞýlÃÓIlûöÞ˶/•ÏÖØWS möFçui jf¤kĺ¯4ô)â‘ ÔÞØøZ“áÒϧE’ËÎŽ»X$ôùS'jkT°Ü9­ãnG{e¶Y¶·²û§½]Q(a1oãÞ@dµ°­¡wŽ;{íï(®U¢´¾`ù6u]»uìQ>ÿð²/Pùcõ 5 €ËOμ È„^‚­P¨0Æ)£Z½‚ýD[CÕÒÑ&+ÿ‰˜ \K¼àqþbIß=¿?<â›Ãáp8N±‘Ñ>£}F{ ¥yJó”æ@ü‘ø#ñG€(Ã(Ã(Càýì÷³ßÏÞÆ¾} ¼t}éúÒxtáÑ…G€÷•ßW~_ù‹ oã6nØ‚-Ø"ý¸ª÷Uï«ÞœÌÌÌ~iýÒú¥¶½m{Ûö,oZÞ´¼ ˜T6©lR(µ¡Ô†Rmmm@³¾f}Íú@–u–u–5 Ú@µjƒïï—·.o]Þ˽—{/÷,}-}-}ÙûY&oQV³ºñºa:Ù€\žÜ5¹Õ@ÌéØÀ8ZbŸU|Çyoñ<²`óÖ2Ô¢3¤ý[y»—ewڈɼê@¸YäÍŽÒËëÅë¾×É‘þ¾\žÜSÙ#€~œîcÝšÒËÉæË†ËÞòeóÍóÿ¥ab®a6㟠¾_&ܤué/†0ËðÈÈ!ÿ¼ØôóûE7A'I»”ô÷rNÊ“×îl O.¯bž+ yÈxgªóþ ¬œ’rpBƒº­þ-LF":þƒiÔ†hÑ·~”Š¿}œÿ…<­çÍ›7oÞ<æÕݬY³fÍšI߯fÍš5kÖd·FFFFFF,Ù$E`áJÞÍEEš0ú£Ië$÷'A­0 K²X\P7%Û¤ˆ_ŠÜ&ïi²¼ŒÈ¥Ho‚&*(¢»0$ËQ= ÞäiM‘Îl„¶Ò,fI¡¸°þ–´Ú ÷‹z?H„Siüè}FÂ1EÚÓ ƒ£G=z”õE‚“÷÷½{÷îÝ»Çb¢¸?G…AžâtÿP$?EºšP!O}ŠHÿV(Y)EÆ“õ yØÓÿé¾ã” ªÇÕ•Ô»mÃ:;vÐÖ¬óý®ÝZøtų{WÆs*ze‡ôüü¶×*,rT©ª 4ÝÝ6©Ýk õqò¾¤P WqyÐQïß|ø_ÆE)|ìÃ_:-©Ï×HÓl¨LQ­¨ ½:ÝÒú½ôÀíëÇ5\\ô>iu¼*0Äu&HŸ–ªžz¸99°þŵ@ß #\GkØ\´~Šîø¡aäÉ?Ël³t±² %/‚ÂUÅ©Šþ@yTÁ?øÎè D¨‡v­˜ `ÂÔ~¡½fàaáíˆ ŠRøèàì ÿ‹ð1$‡Ãáp8ÿa„›ÂMá&dšdšd $õIê“Ôˆ Š Š """€M!›B6ÁòÁòÁòÀ³QÏF=î_àV'‡ÃáüdǪ̂™QˆÊˆÊˆÊžy6æÙà¼ëy×ó®Àæ­›·nÞ xºzºzºíǶÛ~,`–e–e–Å"¡dëÊÖ•­ èšëšëšV—­.[]jeÖʬ• t¾ÑùFçÀd‡É“€}šû4÷iJ™J™J™ÀÀСCÖ+¬WXGO=yô$p÷ÈÝ#wïußë¾×’B’B’B€\õ\õ\uö þÚÿµÿkà€p@8 sRæ¤ÌIúLë3­Ï4 ±oc߯¾€}GûŽöRÛJm+µí+‚w1!""(}Vú¬ô/–žÏ=Ÿ{>:%tJèøÎòå;ë Áû7§Ã‘¶-ZÎâõ*'Zº58Y¶èû߬4ý^ àL› ¯áæ‘7¾ŒD6+ã`zxS6¤Jhbáõ½.÷®aÈK¦M>”bôn?›w6¡ºïÏJÿeù×#ߺ±×””ñOé³pÓ:&ps1²Ü6XôÐvxj?¸œkÁ­n¼N¢v)àiÅ{_9 9msø£×/ƒ"JÉ:ƒ’®]»víÚµ…G8“¥Y‡PÒKŠnÕªU«V­X¤ë;wîܹS°ŠÜ¤ˆMŠà”fåñ£Pû$“9R2EIÈr„„Ý’ÂÓÓÓÓÓ“ ™”LññãÇ?fåÚ´iÓ¦Möš¼’¥]O )Y)/A×™"Ð¥YgP$°žžžžž^áÉ%“AJ²zõêÕ«W³‰IÏmºoÉ…¼»¥áãããããÃ"ê¶5†›››››z¥E¸KF@S¿•ôçˆ<Å)Ò|ûöíÛ·og’+ $!Ÿ’ÈV­ZµjÕª¬¾â‚¾¯¨ß(©' 휟ƒÒ•NÊ‹}¾ÛÞnîúà·|{Å¢ï¯\G¥‘Ê @¥ŽJc•@~¯|Û|@ë¡Î}fÅëÕ°©fwÊ>Pú6»þçŸÝ€ð~!ÇC^2OeâeRü<›NiÒþ> Ÿ¤°TáˆÓ±§Ô€ Þ'­W¬û•»mwµ£¨½3yn:½ŽT|ïvIzù܈ܾ¹MÏáCF˜\+sañ¹;€Ñ“«ej|Ôø¨,QY¢²€Œ`à*®âêÇ{‹¯{wt@tøâu*RQ ÙŸÝa»Ãv‡ÇxŒÇ–x,ñXâ ý4ôÓÐO€ZyµòjåÄAübŸîâ`øšûœ–Å®=±i0Rv¢Ù´š€eMsÇ2—€êAN«4)¸_˜ÕûÔˆ9@ïÀ!~£»rfr×ä €IUFG­ §X®Ý‰–s›}<–x•›?8ÒáīӾ@ÇCÎv­[¬×ÇcUì†q€Œ«‘ÞÚª™V㫑߈u#77ÝѨ:øš3Êê1Çm]¨\TÉW®´0j¼°ø9þ„~i{²åª¦JÀÙÿkïÎãjLÿÿ¿Úí§DŠŠÆÒbOYJ˜ÄX²Ïˆ Y³o‰¯»±e™±‡’m¢¡LÖ"ÚUjZNiUi9))÷ï3×ïö)MÌûùOs:÷¹îû¾Î}z˜×ý>ïkPȹÐo€ öÝ?ÔX€Ù˜ö†MÞÿ·qþö_§Ùp\Ä|sgڵယãcô2µ2±Ò,3^ʽä{€ÿ‹ÖD_:±Ö³fÍš5k²Ö&,XbÛ±Š\[[[[[[~‘Kæ§Ÿ~úé§ŸøÞĬÒuîܹsçÎå{C?~üøñã@lllll,_yü±‚o†µxa‹w²Jev|¬EÖ-[¶lÙº’ÂZ=lÛ¶mÛ¶m|K™™3gΜ9¸uëÖ­[·øÞѬ"–-:ÊnL°ÅÿXÐÏÆcÜuYtsssss㯓¾}ûöíÛ˜1cÆŒ3øžð.\¸pá_ÍÞÿ†œ;wîܹs€‹‹‹‹‹ ÿMÖ„µxa‹yjjjjjjò¯gûg, ˜Ùb•¬÷7‡[÷ÂÇÂXVÉÍlv¾lqGöþ°–5ãÆ7n?ޤ?GìEaaaaa!ß“Ü×××××—ߨ~ÂÂÂÂÂÂø–-¬BµÆiì†È»j×®]»víøÅ^ÙõÌæ­±ë¼•1ªB5 ÷÷zÒ®ž¸pë\`-ê›eÀèn“5§ìl8€>f½wƒO"PœSx¢ð çÌ~°_H§J?•^ Ø”õKwˆ‚3~—½h ÄïˆT|xSÜÃÚúµž'/5^.x9XY5ÇrÆ@ñÂ¥O¯W btÅ‹Öö×ÛÓ›¨¶S{¨Þèegß»¿ðgÂe«ßc¥Ûè=Àä¹ùâoœü¿·×8Ø´Ø,hî­`0¸ srõ‰À%k¢ëä~€¬ìÙׂðп{ž_¹î¿ ;jÒ[ÀV¹ÿbÇ®À¬ÁªÀA‡/·™;;œÊ¬?ÿÌ<¿&`°bï¬Uî[¥§Ö 6­LÏ·ÛöÍÛþß„BÈ?¨ð¬ð¬ðÊRÊRÊR€Âþ…ý û¹¹¹€PW¨+ÔRV¥¬JY$$$1Ãc†Ç žä<Éy’ó;ô†7¼µ8µ8µ8ÀÒÈÒÈÒpáþÂý`ZnZnZN0œ`8hq·ÅÝwŽ:u:û4öiìÔüÔüÔÞápp„#ßðûÖhÖöb/ö¾Ãx_¸{Ž÷ï9RRR€üù ò_Q%«J¹ŠM“C€¿ïþ_Wßþá²÷{  {„}Œ³àp­ÏKÛ;@Û3“ã@¶~î/yé@àã?愼^(¼xòâO`÷ô­VëÌ1ßpÍ ¸2òZîõ4`ɺ¹ 3F©†¯Zžô,Õwnøï÷‚£\§¸×úÔôº\vº:ñzpiÌ•ל€-óÖžY) h<ÓàÔ…_μLùõݱ?£Žµ;¹Xl±Òl-€ä_SuÓ~ºÝ³µ4îØÜóŠpŽL?qí´pûûuíÝÚ6‹^éïK±Rq©b@¹J9KéðKÉaµãƒœ_r óÔ€Ÿç®;°*—ßî¿‚g,0Û´iÓ¦M›øžÝlñEÖ2ÃÄÄÄÄÄظqãÆù®nÏd333333>c­Xëü±ÅÿXÅî°aÆ öñÏ›µÎ¸yóæÍ›7… .\¸ðòòòòòâƒVV1Ízš¿mOðeÈ!C† áƒTܳ ’Un³ šUb³ÞÛ,f-_Xe2«ä­Ûã›È×®]»ví|²@Q$‰D">àd=–YÀÛÔ²Ênv±@šµÔpuuuuu­ÿzvœìýóôôôôôäßÒÒÒÒÒRþ:d‹"Ö ö?Örƒ]ç¬r~Á‚ ,à+ÏÙ —£G=z´~OnIŽØ<³'Ož¬å¿lz¼u"¨›³Xßaiû…>ÀoŸ€¯€}­³:wdd/ÉF‰±gb¼ô¨”åÉßV–Ý=zd#‹~x6É•w¶‡§ÊJ ü§¢ÐÀÔ#†ªþr?9#ÐU/Òh}æÕ©Ë@JM¼G€u-÷<üõ$ {I¶¥ìõ÷<©7è>lƈUW\wXÎ ÷aGÜðí@ê„T²T° Ó{ÐOÎÀ¿&_ÿ!˜då5Èp^7*eÌ$~QO_ë=q>º@·r»Š>?6=ú™;|Ïã²ÓÕyr0pfΑó‡Fî¶.IÖýœï òŸç4ÏöŽÉïóß] ˜ú³¢ý>à»fãú}Ÿ/Á è !ÅqŸj™B!äã{yõåÕ—Wò–å-Ë[Ïž?{þì9P0±`bÁD +,+,+ H·L·L·’ö'íOÚÄÉÄÉÄÉ‘³"gEθX.–‹}÷ý›sæœ9t²édÓÉ0?n~Üü8ÐZµµjkU åâ–‹[.še4Ëh–h Ô¨5pNÀÒK¤—H/y÷ý’/ [ÜòžŸ‰”‰ÐåH¤å­D@ñ ÑuC•=ü;K5I7ʈ¶.ÜñKO ÄáFÅCà‰AΩÜj@¾Zþ„Ü÷@Ï;]wu~,]7/¦`{£ç¨nî [,xÖê™à¹Þû¯Mm€óïy¥êeYåû³$“‹­S€9;¦ýßä!À¤ºŽö©?Îoc¬/ŽÆÅ÷­þ”œXGXu|CoÕª3MË€ ¾£¶èìºMn}býífïYôçŠàÈd?ÿÓ]€rÅìÝÉj ï÷·‡+ö»<~{x/Ñ5Ò8Æ0N5|ÕÒ X´iNÓéÛ€‰‡Æt‰øüæeµ÷†í?¼Wo\½m5ð\.Ïý¯@¡Ja½Âk‹±Å-W®]°%yéñ•  P»¨c±¡¸eK‹@`òÁ ]Çøó·Ìr˜*d_Êò‹S~ÄãÛ3ûÀð£®Àʵ?ÛÔÈÖöª™ <° -¿<h“lm¤‰O.Ö`óðuÆËÄÉ•›n—Üù oàò>X Î*³#"""""ø–„| †Οz P•Y³´v=°!z¥Úض’>ª¯<¡Ìº48œ·3~{àÆ‰?n])rV>žµ¨½\ã\Óh9ÏØ¦u ÀI8ÒrÔh`‚™û¡™€Üß­DêJwHÖLÖv¹­zßî_¼Urs’¸õÇË~@ëÉf÷Ú>܂ŕ×ýþ^³®ÿ;>×V-p½ÃåÚÀæÀÍNÉ£Ó Þþü*ËŸÇ=ßôYlîm\…˜>3ËN%ßø¹á×­ï±D°Ð¸ sªÓ‰§@ømáõÜÕõ·»¹äêù 'À/f[Æoš$›&Ì‹hÌÖ.ìO8•:'³î/³Zá4ùIU¤úÚ7ý¸ñœ)§?óËÐ=ç¯ïážÀùŒÍ!€@O{¼N`{ÙÑm@[ñ8^ßšsï°Ë×"7=ÿqÉ`šÇ‚5 }_Ÿk´:ܼZk\ýí)ø&„"YWpW€Š1c*Æ¥~¥~¥~@¡F¡F¡»,wYî2@( …B epÊà”Á@Âï ¿'üDDD9wrîäÜy÷Ýk\׸®q°,´,´,¾qùÆåÀôºéuÓ뀡™¡™¡Ðb{‹í-¶:Õ:Õ:Õ€Æ)S§Õ|Õ|UºÓNÞÑç|“7{×à–ü·QðM¾f|“ÿ‚ÿjðMÈ—ä]ƒojuB!ä½¼xñâÅ‹|`ý,ôYè³P ¿]~»üv@Ö®¬]Y»€´š´š´àñ|ü#DÉDÉDɼaàÁŒÁÿ°ã=؃=@»Èv‘í";y;y;y ­G[¶@ë¤ÖI­“ƒ~ý úÍN7;Ýì4 ¥­¥­¥ ¨x©x©xŠ]»(v`+X½a?ýЯ÷8ÞŒÍØüÚãØ’~!„B!„ò&|BÈDí¾Ú}µû€JÅJÅJE l~Ùü²ùÀÓ”§)OS€\‡\‡\ ãlÆÙŒ³@JÓ”¦)M„U «VÑùÑùÑù@Þ‰¼yÿTÁvwq€5¬aÍÿZËOËO˰tµtµtæxÍñšã˜n2Ýdº hUÖª¬UÐb|‹ñ-Æ:wtîèÜÔ;ªwTï(§)§)§2É2É2oø ‚Œà7üÞ¾ð•ôìB!„|¹XOñÞ½{÷îÝ›_“BùœQðM!Ÿ»|ä#(J+J+Jžmy¶åÙ _”/ÊY³&fMÒÂÒÂÒ€$‹$‹$ î—¸_â~¢#¢#¢ÿ¡×,´¡ í׳ŠÿÖ~ûýí÷ýªûU÷«ÌýÌýÌý€ÖÇ[o}0P1P1Ptë.Ö] h¥i¥i¥*Uª UU_ÿ£±‹±¯=þ{1Çÿï ÎàŒ¤'B€¦Ú—¿v¡6ó»OTTy®Â@¢V'„ÿ~ýúõë×ÿI!„| (ø&„Dd!²Y¥¶¥¶¥¶@¡_¡_¡£ž£ž£d,ÍXš±H¦S„À#§GNœ€èKÑ—¢/ 6lx‹]ÅU\åjoÕÞª½°L¶L¶L<ª=ª=ªÓ‘¦#MG†× ¯^ôLõLõLííÚÛµ·ê/Ô_¨¿TTTÞb¿ul¦N¥7!„|©ú†ØéÙÔ}awÊf€$I!Ÿ 6lذ jx;))))))@IIIII hÞ¼yóæÍÁƒ<6lذaÃ>þñ^¿~ýúõ뀷····7pøðáÇFFFFFF’žÍÆ¥¥¥¥¥¥ÆÆÆÆÆÆï?Ί+V¬Xܾ}ûöíÛ€–––––ðöã#GŽ9r$ÀVÛºuëÖ­[kkkkkú÷ !„ £à›BþÆõäzr=b©b©b) xtñèâÑ@~h~h~(Õ6«mV[ mgÚδ@RMRMR ;%vJì Ö'Ö'Öç Ç 1¯=.F1ŠLÃ4Lãݱ°caÇBÀñ€ãÇ€¹‚¹‚¹`ìaìaì$$$º}tûèö´NkÖ: h´Öh­Ñ9.s\æøkû™ù˜ÿÚã ¸€7¬¶M!„ò®’’’’’’€7nܸqèÛ·oß¾}iiiiiéúÛççççççþùçŸþ :tèСCÀÒ¥K—.] ¬_¿~ýúõïx øã­¨¨¨¨¨ô,6Îßßßßߘ:uêÔ©Sââââââ÷/>>>>>žŸ&.....èСC‡çÒ¥K—.]BCCCCCùß?{öìÙ³g’ž5B!DŒ‚oBÈOÔ_Ô_Ô(Y]²ºd5P8¯p^á< '9'9'Ȱϰϰ’ý“ý“ý„¦ MšQ«¢VE­ gÎ*œõ†Y¯jæÎáÿ°é¼¦óšÎ,œ-œ-œ{%{%{%À¤•I+“V€áFƽ2½2½2@{œö8íq€z„z„z ¡¡ò¦$¿àüò'>ó0OÒ³O!„\¾|ùòåË€¢¢¢¢¢bÃÛ=yòäÉ“'|ˌ͛7oÞ¼˜3gΜ9søŠðÍÉÉÉÉÉ HLLLLLü÷•ÓŸJxxxxx8ðüùóçÏŸ¸qÕÔÔÔÔÔøq/^¼xñâÅ·¾/\¸páÂ@YYYYYùÃ!„ò!PðMùäª*ª*ª*Q(Hù[ò·äo²DY¢,ú}ê÷©ßIaIaIa@l§ØN±€ø‰ñã'¾aà†7<‹³8 @ R,:Yt²è ’$=H0Ÿf>Í|`Üø‡qÀà˜Á1ƒc€®Š®Š®  ¹Hs‘æ"@+ˆÄ˜Žé˜þ†ýôE_ô}íñLÌÄLIÏ6!„BÈçC_____˜;wîܹs™3gΜ9¸{÷îÝ»w#FŒ1âÃï—-Æhnnnnn.éY<6;wîܹ3|{zzzzz6üºÊÊÊÊÊJàêÕ«W¯^ 0`ÀàܹsçÎ{ûýB!Ÿ‚ô¿‚ò_Q>¨|Pù à‰þý'ú@ÔØ¨±Qcß_ýþê÷WÀn•Ý*»Uµk=ÖS¦8L‚AÀk=U”T”T‘:#uFfVfVfV€ŸŸ0þâø‹ã/+]Vº¬t®g^ϼž èGèGèGó‹çÏ/ö&íMÚ›\i¥ý•ö@t~t~t>­ž­ž­”*?T~ˆï9È~FEGEGE¾Ó}§ûN–ï[¾où>`ÌÄ1ÇLl‚m‚m‚6çÛœosØl6h8ð&„B!ï„U 3ì߉u±–$‹-Z´h``````((((((íÚµk×®°wïÞ½{÷6¼¿S§N:uŠßkùQWzzzzz:0f̘1cÆð=°Yò^½zõêÕ‹oÙÒ˜ÔÔÔÔÔT~}úôéÓƒG„ò¥¡ŠoB¾bU¿VýZõ+ Z+Z+Z y£òFå²þÌú3ëO µmjÛÔ¶@âÎĉ;ØêØêØj ¡}Bû„öÿ°ƒS8…S¯ýd¼à/Àò¹åsË瀳µ³µ³5`vÛì¶ÙmÀXÎXÎX0˜c0Ç` ›¨›¨›höÑì£ÙPõQõQõä ä ä þaÿšÐ„&€8Ä!îµß— %’ž}By{¥nË…)¥n{)é£!äëtoqêètm@j ÆJ¹ Óä~—] (œ•µ“Uä eoËúrÝe†É˜rwde„€ì(™Ò‡Ù<™2™eÒ]¤›2M¤ŸI'2¤NIù5µ\>W HÿÌ á¾°IÒgüyª®®®®®æ;YYYYYY¾ò˜aÁê·ß~ûí·ßòÁ, üLLLLLLø uÆŒ3fÌrrrrrr€5kÖ¬Y³æí‹©Ý»wïÞ½;X.\¸páÂ…@“&Mš4iœ}úôéÓÈÍÍÍÍÍ­~»wïÞ½{7púôéÓ§O7<ïŸúsôµ¹fz>Y…¹h»%S!õ<`ìÜ6¦ÓUIŸ!_8}JoFÁ7!Ÿ‘Z©Z©Z) "¶"¶"(=Tz¨ôðTñ©âSE {nöÜì¹@ÆãŒÇûû{ Þ?Þ?ÞˆÒ‰Ò‰ÒJlJlJlþaGGpG^{,„B@o¼Þx½ñ€E–E–Eðí”o§|;0¹lrÙä2ЪU«V­ZÍ74ßÐ| ]ª]ª] ¨S§>Pžª=©iògäÏð“Ï͹¿ø è5KÈ—lXÜÿû?Öøã bÊÿ<þÀá×_DdWœÆÿ)8L>êfïv88ñàăojÑö•Y½zõêÕ«ù€—a߸c‹²ŠaV ½|ùòåË—-[¶lÙ²%ÿºcÇŽ;v ¸yóæÍ›7ùâu+ŒÝÝÝÝÝÝù*,He¿oÑ¢E‹-?~VAÍO@³À•a­Ylmmmmmù@2!!!!áµïz{{{{{ó­AX…yÝÞâ,d-Xöïß¿ÿ~þõ††††††ü¢¡8pà‡{ߨ¼³ i¬× ¾Y€Ê‚þ·]Œ”ÕlÞºtéÒ¥K¾Òºîõâêêêêê ´mÛ¶mÛ¶ÀÚµk×®]ËâlQUV!üøñãÇó•Ö ¼mllllløùgÁ7 âËËËËËËù¹îõÂnp°ÑÑÑÑÑÑ|ð}ôèÑ£G………………@HHHHHбcÇŽ;òã°ÅIÙçàüùóçÏŸ¯?_¬âú¯¿þú믿øÏ «G_‹}×V ü6Û?¿ýüöóÛÀ—+.W\€9s æ9¯rzå¼ -ÞnGÒŽ¤IÀáá! å¨å¨å(é³%ä¿‚oòŸT»­v[í6 âAŃŠ@Éô’é%Ó§qOãžÆÙ6Ù6Ù6@ƉŒ'€dÕdÕdU ~Iü’ø%@TFTFTPfZfZfúÚÀ·q·_{‚„ØýØÏÿZ_ /ÐB:…t ëÖ¬ ˜¬6Ym²hUЪ UÐ|DóÍGÚÁÚÁÚÁ€ÚrµåjË&VM¬šXýà ¦#¯÷ÄKD"%=ë„B!’cúØô±éc 0¸0¸0è4´ÓÐNCìçÙϳŸøýÀ|„5?[¬²YQQQQQ‘ïI}âĉ'Nð-XØXohVÎZY°Šä·Åz$7¦¸¸¸¸¸˜¯ÄeAßûW6 ¶ÃGIaÁ7k±ríÚµk×®ñ7*X‹Öã\GGGGG§ñqÙûȰ`½±% k9ðé[¶lÙ²e ß³šUf³`™Æßÿý÷ßÏŸãìììììÌÖ¬<ûÉ‚q¶«€¯û>±J|vœ¬5kÑÂZ£° î—/_¾|ù-ÍØv,xoLcߟêsôÕ;Ó8 $I“4ð‘ó‘ó‘vWï®Þ]Íof3Ñf¢ÍDÀOÓOÓOè%ßK¾—< c&c&cÀ f0{ï£ „¼ ¾É¥j]Õºªu@Ù‚²e €â5ÅkŠ×y…y…y…@æ¨ÌQ™£€Ôë©×S¯‰æ‰æ‰æ@ìŽØ±;€Ç?xüà ûÁ~ ïWÆPÆPưª±ª±ªF† ˜-3[f¶ 0Þo¼ßx? /«/«/ 4ÝtvÓÙ€f‚f‚f îªîªî H;H;H;üà žÀ œxÃïÝáwIÏ>!„BÈ—Oà p8i‹Ò¥-†:`è ¨gPÏ žÿ~üA¡ƒB…ª½U{«ö–ôÙJ[4-æÇZˆ°ÞÂì÷,h¬‹µÈ`·õ2®‹U7†í‡ùá‡~øá>P}[¬R»îx_ Öšƒ«€¯|Ïš5kÖ¬Yo?nÝùصk×®]»øÖïkîܹsçÎå·ô÷÷÷÷÷ç+íÙÏ€€€€€¾Õ ëÙÍ*ÆÙõ·lÙ²eË–ñã°– ¿þú믿þÊÿdÛ5jÔ¨Q|ÀÍ*ÍY΂wV‘ÍZ¼°yd=ºëb•Ö¬b½1ìFScóÿ±?G_›b›b›bàü„óÎOŽ»ê|Õùª3ÇÅÍŒ›7“ãrÊsÊsÊ9N”%ÊeqÜ«u¯Ö½Z'éY#„B!ÍJn%·’ã–š-5[jöþÿîd?¹-r[äÆqÙ?fÿ˜ý£¤Oîã·>àÏ[\ñÝøëÄ'ÿº³gÏž={¶þvâ!'^,ãÄä +®Lå8??????Ž/VÉ?/^”’߯¸ÕljƒF~?âE?<<<<<œ^ܳ»ñã÷ç8q>ÿ{q‹Ž·^Ḫªªªªªú¯Wòsœ¸Ç7ljiŽW\sœ¸… Ç………………5|‰‰‰‰‰‰§¥¥¥¥¥Å_¿ {¬¦¦¦¦¦Æ_‡ W óóQ—xQOŽkß¾}ûöíŸ'q‹~<ñ7øç?ôçèkS©R©R©ÂqWͯš_5ç¸>¢>¢>¢ú×ììì9îVú­ô[éW£]£]£-é£'„¼ ¾É'ulÁ±Ç4ü? rMåšÊ5å¸n}»õíÖ—ãÜâÝâÝâ9nȘ˜M1çßÍ¿›7Ž ———ç¸4»4»4;Ž+N/N/N—ôÙB!„/ݱ¢cEÇþEáEÝŸú£ôGéâ¸í´?Оãr·ænÍÝ*é³ü÷Þ7ø~ôèÑ£G8NVVVVV–ãÄ=‘ëÇâÊ`~üÍ›7oÞ¼¹áq§M›6mÚ4~{qoiþù†‚o†Ôâ^ä'î¹]?,8WH󱸢ߎœ,pÌÌÌÌÌ̬?^VVVVVÇ))))))qœ¸Ç4ÿ<{,®Pæ8qïû¿oß¡¡¡¡¡¡ü<‰[„pœ¸EFýí ¾Ù¼°y·á8qëúã±`]\ÉÌqÇ>|8ÿ|PPPPP¿¿ß~ûí·ß~kø|ÝÜÜÜÜÜøìFÇÒ¥K—.]Êâ ¼âE=9ÎÄÄÄÄĤþ‘:tèÐãÄ-G>ŽÜÜÜÜÜ\>@gÇÏ‚xF܆^¼hýñX°Ï泡àûC޾TÕúÕúÕúw7änÈÝŽ›0vÂØ cëÿ½Ö;¯w^ï<Çù.÷]ãžuyÖåYI=!äß à›|R¯Ž¼:òêÇånÏÝž»ã*µ*µ*µ$}T„B!„ü¯°¢°¢°wÀ×^\{qíEŽíííå¸Ëc.¹<†ãìµìµìµêoß|UóUÍWqÜîÀÝ»9NxRxRx’ã8΃óôÙ7î}ƒofÞ¼yóæÍã_¿|ùòåË—óϳñĽŽù@ZÜk™ã8pàÀŽ›4iÒ¤I“øq¦L™2eÊ”úûk,øNJJJJJâ8uuuuuu¾‚wåÊ•+W®ä8q« ޳³³³³³ãÇ9vìØ±cÇêïOÜ«™ãÄ‹ òAó¦M›6mÚÄq;wîܹs'¨²`XÜœ‡m_7ˆn,ðmHcÁ7 †@ à÷ëíííííÝø¼Ö ¾VAÌÞGSSSSSSŽ/NÉqÛ·oß¾};ÇòóÏn”0,Hg7ØûååååååÅq‡>|ø0Çyxxxxxð7 Ä­NøqRRRRRR8NÜœXÅ=»¾Ä=¾ùó· áÇ·ÄáŸg×ç™3gΜ9ß»Á#^ü”ßžØ «h÷†ç8þó!^–žÝ `ã•–––––~¼ÏÑç®ênÕݪ»wwæÝ™wgrÜäᓇOÞðßíM^›¼6yqœ0B!ŒôÑB> ¾ !„B!¤B¡Ð†ã¤ò¥ò¥òPò"ó"ó"§Ì§Ì§Ì‡ã;v ìÈqN 81àDÃãy™x™x™p\ô¸èqÑã8®Ú¨Ú¨ÚHÒ³Áû·Á7 ètuuuuu9NÜӘ㒓““““ùíXëìÙ³gϞͶ¬‚—¨¬R¶nå5ÓXðÍ$$$$$$ð•Æ,¸f•Û]»víÚµ+lj{G7~ž,¸e* ZYå/ ²Y[ ÂY 6O,¸|Wß ½¿ Í×Ûߌ¸÷6ÇõìÙ³gÏž|¥; Úœœœœœ8.:::::ºáqX…¶«««««+ÇéëëëëëóóÂañb“ _¬‹xqL¾E ”;wîܹsgŽ÷ö®ÿzvݳ U`³ë“Î,g­UØ|5t±o°ë]7ìzdA~ÝཡÖ/êsô¹(íUÚ«´Çµ jÔŽã†ï¾øþ†ÿž®Î[·:ã’g%ÏJžÅqœ§ÁiHú,!Ÿ‚ûB!„By£rûrûr{ G§ztm{´íÑ6 }iûÒö¥@œZœZœÚ»û<ãyÆó àÑ£FÀá¼Ãy‡ó€#ÍŽ4;Ò¬þöNkœÖ8­\Í]Í]Í^“{Mî5hfÖ̬™€D BÒ³õù9qâĉ'øÅÅ7¿è!Ÿ¡P( qÐ ˆo4¼ýŒ3f̘ˆ¿Iú,þ½ÚšÚšÚ cIÆ’Œ%ÀÕ3WÏ\=ìtÜé¸ÓH:˜t0é ¿½j²j²j2°òáʇ+ÃJ‡•+Œ)=)=)=IŸ!D¤%}„B!„ò¹S Q Q b´b´b´×=®{\÷{ïソ÷þû«l¨l¨lØqvœÖ=¬{X¨™[3·f.Ø*±Ub+`³Ûf·Ín@”F”F”àâââââ4/o^Þ¼z õ@ê0µxjñÔb H$› 6l¸x.ž‹—ô,JޏÇ2ÿXÜ"CÒGEÈÿòñññññÄ•ã€x±ÉúÛ‰¿ øûûûûûâE6%}ôoïÕ‹W/^½rŒrŒrŒ€€Ö­Z.s\æ¸Ìdådådå€6?·ù¹ÍÏÀŒ¬Y3²uuuÀoŸß>¿}@nenen%P¦]¦]¦ ,³pÌÂ1@ëi­§µžF7! ŠoB!„Bù”:—:—:‘ž‘ž‘ž@€e€e€%à£è£è£ØðëFqpÄA`¨ÿPÿ¡þ@—É]&w™ ´ºÙêf«›€ÒN¥J;%}vÿÞÓ§OŸ>} Œ=zôèÑ@ddddd$ n©¤¦¦¦¦¦Jú( ù_ì›ݺuëÖ­ ^èß¿ÿþý–ÞâV%ÀíÛ·oß¾ ˆ[¼Hú,€Ê¤Ê¤Ê$@è#ôú÷.ß»|ï2PPP\¬¸Xq±¢þë4K4K4K€9íæ´›Ópöpöpö¾Éþ&û›l@q‡âÅ’>;BÈ—„‚oB!„BùZœÅYœŠŒ‹Œ‹ŒØÅ±‹cWܯ¸_q|·únõÝ ä‡å‡å‡Õ¹ZŒZŒZ 0î츳ãÎýƒúõ,”-”-”î-Ü[¸ £F+Œ–ôÉ6LÜ3÷@æ+¼======qOcI%!o&îñ ìÝ»wïÞ½| ÎXYYYYYîîîîîWþÇ?®õõu '#'#'ˆíÛ3¶'pm嵕×V~~~@áÓ§…Oë¿^¿H¿H¿pç:Ïu0Ðd É@ ýŠö+Ú¯Ô¡ú"!äC¢à›B!„Bþc*…•ÂJ! T* •‡ë®¸   އ;Öðë›­l¶²ÙJ`”ó(çQÎ@¿Ü~¹ýr޲e;ÊzŽzŽzŽ€‚Œ‚Œ‚Œ¤Ï–òOjoÖÞ¬½ æyyy@R`R`R p;ávÂíà܃sÎ="[D¶ˆlÑð0?;üìð30ÄaˆÃ çêž«{®ÚŒm3¶ÍX@½H½H½ÀTLÅTIŸ4!„ð(ø&„B!„ò~Îà Îå«ËW—¯Ò«Ò«Ò«€ˆC‡"üðGpfÇ™gþ¡7¯’—’—’à’ï’ï’ØûÙûÙû,X< - - -µJµJµJIŸ4!’U^^ä{ä{ä{ “&%Ln+ÜV¸­\èv¡Û…n@Ü7qßÄ}Óð8½:õêÔ«0döÙCf6mÚ<ÌΚ5; hÕ«5Ú.µ]j»¤ÏšBÞß„B!„B> ÑUÑUÑU sræäÌÉ@T¿¨~Qý€ñ!ãCÆþþþ@¹{¹{¹{ÃãôñéãÓÇ2 d@е²ke×JÀô®é]Ó»€ž†ž†ž -”J %}Ö„4¢Õ¨Êz—õ.ë d.Ê\”¹ˆ•‰•‰•n”Ý(»Qœ?tþÐùC@AhAhAhÃÃõ½Þ÷zßë€Ó+§WN¯€[{lí±0Í6Í6Í´c´c´c$}Ò„òñQðM!„B!ä³ò¢Õ‹V/Z9i9i9i@ÂÓ„§ O»[în¹»¸¼ëò®Ë»€èêèêèê†Çi¢ÔD©‰àܹ…s ÀöíÛ€…µ…µ…5`$0 ‡ÀCàÈ“'?NÒgO¾xÝÑÝŠÜŠÜŠ\ wPî ÜAÀcãÇÆˆeË"–×®)\SîVÞ­¼ûßdI—I—IFyxäaÀ~ºýtûé€u°u°u0`ìnìn쨪ªR½¥zKõ–ô$BˆäQðM!„B!ä‹ô*ðUà«@ d{Éö’í@†M†M† ããã Ü*¹Ur«¬¬¬ ºt+èÖðxò2ò2ò2À€üùò›<›<›< “G'N€ñZãµÆkݦºMu›êÆêÆêÆ’žò±½¼ÿòþËû@éäÒÉ¥“ì®Ù]³»—<^òx ðÐð¡áCCàF—]ntîÅÝ‹»×ø¸Ýt[Ðmàhàhàhtÿ¥û/ÝÌ›7?47knÖÜ Pj¢ÔD©‰¤gB¾<|B!„BùO¨yTó¨æP¼­x[ñ6@/ŒÆñ–ñ–ñ–@xÛð¶ámµµ5 uRê¤ÔI«S¨S¨SØØØÖǬYÚV´­h[¦¦¦ºctÇèŽ4ŽhÑ8(_S¾¦|MÒ³òßQ>²|dùH x}ñúâõ@î¤ÜI¹“€Ô3©gRφ<òhpèý¡÷‡¡—B/…^jï×Þ¯½ßøø6v6v6v@ã>Æ}ŒÎÝ;wïÜ0?o~Þü< ç£ç£ç¨–¨–¨–RÖRÖRÖ’žBùzQðM!„B!„¼I$" ”*;TvÈÏÏÒ~Kû-í7 aT¨„QÀƒ+®<¸Ü9}çôÓ€p¶p¶pöÛï¦Ió&Í›4,°üÁò ]×v]ÛuÚks¬Í1ÀÀÏÀÏÀhnÓܦ¹ p8 uuu ÉÐ&C› ´¬´¬´¬$=iÿ^ÅÅŠ‹ªÑU£«F"y‘¼H(1.1.1žú=õ{êäúåúåúBM¡¦PHÉIÉIÉâããÈ™‘3#g¾ûþ-Ì-Ì-Ì'{œìq°ZlµØj1`¾Ø|±ùb ÕÑVG[´MµMµM%3%3%3£0 £$={„B ¾ !„B!„àùéç§ŸŸJV”¬(YämÎÛœ·Èš5;k6Z™Z™Z $''ñµñµñµ@ô†è Ñ€Êþ•ý+û¸ãQ¹¯r_å> «« hykykyjKÔ–¨-TN«œV9 (i(i(iòGåÊä†Ë —HËIËI˸ƒ;¸ÔîªÝU» xéòÒå¥ ð‚{Á½à€Ê •*7¢QŽ((U-U-UŠEÅ¢bP°³`gÁN J¥J¥Jåß J%ˆ:Ét’é$´wkïÖÞ 0Ó4Ó4ӌ۷1nè/Ó_¦¿ hZÕ´ªi ~Oýžú=@a¼Âx…ñŸú*!„ò±PðM!„B!„|JäKäKär¯r¯r/ T·T·Txöí³oŸ} ×××ÅVÅVÅV@anana.P,( €¢³Eg‹ÎÏÎ>;ûì,P¢\¢\¢ ”••åçËÏ—Ÿžg>Ï|ž ¼ðbÀ‹@uTuTuðjÍ«5¯Öp‚œ™J™J™J@~üù=€b ÅŠ-åeÊË”—ª~ª~ª~€Ú.µ]j»ÍîšÝ5»š47hnžO' È äAKAKAK@ð§àOÁŸ€fºfºf: ¹Ss§æN@}úõ=€Š´Š´Š4 &Tª %ý®Bù\QðM!„B!„B!ä«"-é „B!„B!„B>$ ¾ !„B!„B!„|U(ø&„B!„B!„òU¡à›B!„B!„BÈW…‚oB!„B!„B!_ ¾ !„B!„B!„|U(ø&„B!„B!„òU¡à›B!„B!„BÈW…‚oB!„B!„B!_ ¾ !„B!„B!„|U(ø&„B!„B!„òU¡à›B!„B!„BÈW…‚oB!„B!„B!_•ÿ5tÇÚñø…‹%tEXtdate:create2013-02-01T15:45:27-06:00;½ ~%tEXtdate:modify2013-02-01T15:45:27-06:00Jà²Â zTXtsvg:comment×SpOÍK-J,IMQHªTH/J,È(ˬR(K-*ÎÌÏS0Ò32×32040424Ö3051UÐ@ájr)p)„d–ä¤Z)8––d8ç縤椦THLO-¶R0*É™A©Y©É%HbjÊ&¦Öjé%Öp™àÔ¢²ÌäTljRP\ÉŠà’Ä¢©Ý8IyœpXªtEXtsvg:titleStart->AuthCompKÕÔIEND®B`‚keystone-2014.1/doc/source/images/graphs_authComp.png0000664000175400017540000011041412323716267023756 0ustar jenkinsjenkins00000000000000‰PNG  IHDR~”]øîgAMA± üasRGB®Îé cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿÿÿÿ X÷Ü€IDATxÚìÝw Víÿð·M%3²ÉŠRÚ‘v!T’JƒöÐRiGS¥½µw´µ§h‘¤=QÊŠRF‹Ìóûãt}ÝMõ<Ÿ×?÷÷¾ïs®sëÜÏ×és>×õã¾!„B!„B!ä¯'^Ù „B!„B!„ü<ð#„B!„B!ä_„~„B!„B!„ü‹PÀB!„B!„ øB!„B!„ò/B?B!„B!„BþE$+»„ÿŽ9sæÌ™38qâĉ'Do'&&&&&ÈÉÉÉÉÉ€“““““Я_¿~ýú Ûý*aaaaaaÀäÉ“'Ož &&&&&&•=šå{üøñãÇsssssóÊî !„B!„ß…2ü!¿Í‹/^¼xܺuëÖ­[€¦¦¦¦¦& ­­­­­-¼jiiiii ½3gΜ9sðððððð¼½½½½½}333333…þæäääääTö(–ïСC‡6lذaÃÊî !„B!„ß2ü!•æÀdeeeeeEo÷æÍ›7oÞmÛ¶mÛ¶-°zõêÕ«W ? üÙ„@% PþéîÞ½{÷î] /////¯²{C!„B!äw£ ?BȯF5jÔF=zôh ¨¨¨¨¨ˆŒŒŒŒŒ¬x;ÅÅÅÅÅÅßž"kÖ¬Y³fM@JJJJJêׯ<Çq'úû‚‚‚‚‚a|˜ÏŸ?þü(,,,,,üyý!„B!„òg¢€!ä¯!######¼—(»ÝÇ?~üxyyyyyjjjjjjÂöúúúúúúÀ’%K–,Y":,¬%xïÞ½{÷î•Ý.>>>>>èÖ­[·nÝ€ªU«V­ZU6jÔ¨Q£FÀÉ“'Ož{öìÙ³g@÷îÝ»wïT¯^½zõêB»­ZµjÕª%ìçîîîîîøûûûûû Ÿ³þO:uêÔ©•} !„B!„üj4¥—òÇcj›6mÚ´i“HkÒ¤I“&M„íX›½½½½½=pûöíÛ·o£F5j`jjjjj \¹råÊ•+B1Ž”””””`ÕªU«V­ªx¿’“““““++++++! 9sæÌ™3gòòòòòòÀÞ½{÷îÝ téÒ¥K—.ÀÁƒ<(ôÖfÍš5kÖ ú©ªªªªª ¬Y³fÍš5@ÇŽ;vì(¬1èãããããHJJJJJ@HHHHH §§§§§WÙW“B!„BȯF?BH¥™6mÚ´iÓÊf걌»¬¬¬¬¬, 44444HJJJJJªý²" pEDDDDD§N:uê”°3dÈ!C†°ùóçÏŸ?;vìØ±cCCCCCÃòûÏ{l*í;wîܹSvMÁáÇ>hß¾}ûöí…µ]\\\\\„â$¬¬8ȃ|Ø·oß¾}ûÊn¯«««««+¬õǦº²)³¥_7nܸqÈÍÍÍÍÍ-¿_ Bõ\6…WÔqØë§OŸ>}ú$¬ÍÇ}¬8[ûUý-ÏìÙ³gÏž ,Z´hÑ¢E•}µ!„B!„ü)(àGùãÕyYÑ 6%˜qrrrrrªú._¾|ùòå¢Û7oÞ¼yó„ÌÁÌÌÌÌÌÌòûÃÖttttttÖä /»}~~~~~¾P,„U ––––––¶ëÔ©S§N€°°°°°0aŠriiiiiiiÀ²eË–-[&¼gJAaEE!„B!„ü7PÀòÇcr^^^^^^ÂÚwsçÎ;w®°Ý€ 4iÒ¤I“&€ð9«fËÞ³@"{oiiiiiYñ~ùùùùùùJJJJJJ€½½½½½½P}xÆ 6lªäÞ½{÷îÝ»À’%K–,YR6àÇú[µjÕªU«ÖÖÖÖÖÖÀ‚ ,X¬ZµjÕªU@›6mÚ´iÈÉÉÉÉÉ“'Ož}ú((((((¨ìÞ”Õ¢E‹-ZK–,Y²dIe÷†B!„B*Ž~„|ƒ/^¼xñ¸uëÖ­[·„€LE¥§§§§§ ûøðáÇ•}V•‡å7oÞ¼yóæ@PPPPPPÙíØÚzÿµqkÙ²eË–-íÛ·oß¾½ì÷ïß¿ÿþ½0.ìýŸîôéÓ§OŸêׯ_¿~} /////¯²{UW¶v#!„B!„ü-(àG©4,³ïæÍ›7oÞ¬ìÞüy¢¢¢¢¢¢DÏ‚ÉÉÉÉÉÉÂû?Ýýû÷ïß¿äæææææVvo!„B!ä߇~„üAXÆàçÏŸ?þ\öûŸ½â& ¸}oÿÊëOaaaaaaÙóaû•Îìµ}y~ö¸|kæfE¯[yýdß—n‡]§ÒŸKIIIIIªªªªªªÂûß=n/v}Ù+Ã~¥?/¯ß?«ÿ´’-!„B!ä߆~„üA‚ƒƒƒƒƒ999999 <<<<<h×®]»ví J•*UªTzõêÕ«W/àíÛ·oß¾ÝnLLLLL àêêêêê ()))))’’’’’’€‚‚‚‚‚àæææææ¤¥¥¥¥¥•m‡M¹eý+o-=a{ÐakÒU«V­ZµjÂöóçÏŸ?¾°ýÇ?~üX¶ÝÔÔÔÔÔTÀÅÅÅÅÅ•••••Æ…GFFFFF†èþåäääääÞÞÞÞÞÞ@Íš5kÖ¬ HHHHHHººººººÀ‚ ,X :°Å¦¨²~_ºtéÒ¥K@ÇŽ;vì(ô}ß½{÷îÝ»¯_¿~ýúµÐ›:ʶc¾¥K—.]ºTøœ]ï°°°°°0ásö¾46ý^ªW¯^½zua¼ØZu¢ÇkÓ¦M›6m¦â²#{511111Êî?bĈ#F¾¾¾¾¾¾Âç,`9zôèÑ£G—Ý/22222hݺuëÖ­…ÿØkûöíÛ·o/LÁ-ÏÞ½{÷îÝ ˜™™™™™ ÿÔ®]»víÚÀ¹sçÎ;W~;„B!„ò§¢€!°®]»víÚUXãŽtüýýýýý#GŽ9r˜8qâĉËîÏÖ da¸­[·nݺèÙ³gÏž=ƒ}úôélÞ¼yóæÍ@‡:tè̘1cÆŒ€§§§§§gùçÇ‘ 4hР ,_¾|ùòåÀÉ“'Ož%|¿bÅŠ+VíñÑíñ™gÇg¤•ý~÷îÝ»wïÚ»sçÎ;wD·7eÊ”)S¦Ûóá{öž}?kÖ¬Y³f•m‡l ÛuëÖ­[·n¢ëäääääÄq|ŠãøÌBá{>ð#´wøðáÇ‹nÏÏÏÏÏÏOØþÑ£G=¾çVÂ÷|&›èö8pà@¡¥Ç…á3 …q,à Çeïöûá3ðÊö›áÃÇgüq°¾×ÓÓÓÓÓã8>ð&ú¼øµ…þL:uêÔ©e·[¸páÂ… …íø€cÙíøêÃÇEÿ÷Æ+á8Žsppppp(»]­ZµjÕªÅq––––––ÇO%.»ÝªU«V­Z%ô¯ôxBù3ñ²8®Q£F5úöWQ?ÈŸ‰€Èq 0`@e÷†Bþ<’•p$„ˆÆ¦„Šblllll,dº}úôéÓ§OÂTY–1Å2šÔÔÔÔÔÔʶÃögZl­8– Ç2Íþ| Sô÷M›6mÚ´©IÇ2ÃXF×ñãÇ?.LµÕÐÐÐÐЮ_¿~ýúõ²í™ššššš ïÏŸ?þüyÀÜÜÜÜÜüû¯[».;;;;;[˜Úú³œ9sæÌ™3B曨þÖ¨Q£FB‘mmmmmmáû¸¸¸¸¸8a ´(¬›"Ë~ߊM)gÅ\ø)p÷îÝ»wïŠÞÿpöìÙ³gÏ SÈ€çÏŸ?þàဴ´´´´tÙv†:tèPÑ™³„BþL¬ˆ›ÑÀ– `—È¿ [²¦¢kBÈ ýé#ä°€æü±ÀQyJO,o?¶Öž(¥‹4ˆºáaŸÏž={öìÙÂ0[KBJñøS~êêêêêꢿ/=8?????_xÏΗ6­­­­­­+~|¶† (?ëºý(öð+OݺuëÖ­[öscS“ÙTr6õ—ýŽJ¯%ù­ÅOv}˜íÛ·oß¾]x­¨ÌÌÌÌÌL )))))IøœÏô½ûýðƒ?ïzBù½Ø ¶d!„ò_B?B¾¢¢¢¢¢¢ðžefÉËËËËË—¿é"å­Å&&&&&&öýý½}ûöíÛ·…b,pÃ2Ðø)BFÜ©S§N:%¬íö£~U ëG|‚3ÀOUþAPQ,SP”½n?Ë·Va…­ÉÇÖ:d™tlmIö;bkí‰Ê$¬(v}˜9sæÌ™3GXk²¢Øu*ý{©hèï XBùoùÖ¤ìþˆíÇîÏJ·Ãþ޳ÆìÁ³¨û 6s€í_ú#SºÝò@—þ»\ÑûöÀ•õ‡eZ~ëx±ãÿ)÷W„ò·øƒrvùó•žÚ]ñýÙö¬:ªÁ¯ë/¿ö›ðþáÇ>ŠLŸ>}úôéB±À¥ô”˜ò'¯^½zõêÕ¯;¿ïÅŠ†°bl +«ÒZú•MµeS^Ë›Úú§`jññññññåoϪ$Ï›7oÞ¼y¿æŸè4hРAƒ„©¶¬ØÅ!C† "ŒSéŒÊï½> +>#êú°×”””””!ãU[.Ñ÷ôéÓ§OŸŠ>>ë?û}B!€půõ'd„³€{€ZÞƒDV•žeà/]ºtéÒ¥Âý!{À¼Åp‹áCá8l©ŽÒØe¶­­­­­­èã9räÈ‘ÂßO†ÖV¯^½zõj!óŸ»dÅ»¶mÛ¶mÛ6ÑÇaã1a„ &ýúõëׯŸˆdŸKß7°¢_¬è t²%XÖ­[·nݺÊþ5BÈŸ~„|–ÇnTXµÛò[l-¹ .\¸pptttttüõkʰ@6•…Ý(•Æ*¬ŸLé =MMMMMMá= ü”öæÍ›7oÞ”­Â[Zé'»¿«**_ÔC8¿E‹-Z´Hôö|‘ !“íw2YÀê{Ç¥S§N:uøâ0B ¬4v½Ø?8X «tF*«:, «ú̈ÊðdçÅ”>?ð³°°°°°vîܹsçN! 'ªÿlmGVµ™e°ö6lذaC`Ó¦M›6m½Æ ;ªÒK!€±_´ ˜9sæÌ™3…jõ,ÃŽÝçñEÁD·ËÖÈe÷!ãÇ?~<йsçÎ;ý²úeõË2ð.]ºtéÒ¥²í°¿ó,`ÇPŠú;Æùìííííí…ÏçÎ;wî\ÀËËËËËKÈèg7Ù};_4¸ÿþýû÷EŸg````` 0ó„=pf™û, øàÁƒ¢ÙýÖâÅ‹/^ ðEÑ€iÓ¦M›6M¸„B¾Ž¦ôò XÆ›bÈnX 6mÚ´iÓFx2ËnäX`ŒÌüýýýýý}Ù X±L,ö9[ã¯J T­ZµjÕªÂZl|õTáF“Ý貌8¾ «P=™fv¾¥×vcXÀM½dOŠÙÚkåâ¾+bÂn`ù*¼À‹/^¼x´lÙ²eË–BF&ë—››››››0•õWcs{öìÙ³g b™xåa7Äû÷ïß¿?`ccccc#ÜÈW¯^½zõêÀ† 6lØ ÈØ~캰b/lœØv¬Ø d³ã°ýØïGÔy•¾=zôèÑ£‡IȦ–³ßk³fÍš5k&d&°©ôëׯ_¿~=ÀWëþaP+ÖÁ÷líFv<ö;f¿ 6>„BþNì>ÝŸˆÂ䲿¥±¿‹,¸ØÒ »ÏbÅBÆŽ;vìX k×®]»v-û 7+++++K º¸¸¸¸¸”=~KÛ–¶-mEü._¾|ùòeá>µtñvßòìÙ³gÏž ÷;ìï+ à±Ì}pd÷s¥±Š,Óïĉ'NœêÕ«W¯^½²Û³$¬ø–¨5rÙ Œˆˆˆˆˆ(»# ²ûB!"Tv™`BþfÁÁÁÁÁÁ×¾}ûöíÛsá8~êÇñSv9ÎÓÓÓÓÓ“ãøâ¢Û;xðàÁƒÙ*))z{þÆHØž¿q¾ç§ÜrÿĘ㴴´´´´„þñ7¤Çg4qÜ7nܸ!´wàÀ”=î½{÷îÝ»Çq|€“ãø€ Ð>Ðä¸]»víÚµKhÒ\¶=>ÀÂq| ˆãø@ÇñOz9Ž/!´Ã?É=.|†—°=_õµìv|@Šãøj¬Ç߀r£ÉqFFFFFFÇx…ñ,¿ÑŽwñâÅ‹/þxÿvìØ±cÇáwÅW_æ8>€Ìqüz¡ö¾4~J/ǹºººººr¿v$ÇñiŽãoÜ9ŽŸªTvv<~ê‘о8 ÇñOè9ŽÏ 举}ûöíÛ—ãøÀ0ÇñkõíñU“…ÿnØï‘ÿ‡NÙ㇇‡‡‡‡ Û³ã³þ·k×®]»vÂvåáÿÁÄqVVVVVVÇOâ8~Ê>ÇñUœ…÷ü†å·K!¤ry{{{{{ +úÊþ•Æø„û~Jjùýà‡Bû|ÆðýðáÇ.|Ï?°ÝŸYÇq|†¼ðw”á3Ø9ŽŸy"ÜG±û †Ÿ Ëq|€³ìqÙ} Ý>à)ôŸˆ–ÝŽÝgòkû–?nìþ„ÝG”‡µÏ?ü¶ß !„üPÀB!„ò×+ðã—‚8Šzå— (ÛÛŸµÇ–‡/‚&ìÇè2,àÇϬ(¿=ö”µÇ/Á"æøÇgÜ ÂøÌB¡ggggggŽã‹l•={@wìØ±cÇŽq?eWx@Ægð— ˜òkF—mäØ;QX“µçëëëëë[þ¸°Žð#„¯£5ü!„B!ÿ:lÍX6•VÔkéµeþŸK¢ß‹Âªà2lŠji]Ë™Ï`K¥°©½lÊ+["…MÝeÅ@øÌwaM]~BÙµû˜8P˜‚ÌŠ”4nܸqãÆÂ¹¢Ö¥¼ó,½¦syEáVí—BÈ×Ñ~„B!„RŠºººººº°–qyUÞ¶†3ÃÖ>þQ¬ú. ܱ@+JÅÖbf¿Ù³gÏž=[X‹Ï¤ÖàcX‘¶[{­ñ\ÚÏ®bÏ/Õ!¬ \Ñqfkþê"x„ò·¢ ?B!„B)…ó°³³³³³Šk°@Si¬¸V@@@@@À¯m XZZZZZþxXÀU§å§ ÅÆ–éÇ2 YÑ-Ö aûŒŒŒŒŒ á}ƒ 4h º¬š=Ã2T·nݺuë&œ—¨À¿æ´P”„BÈ×ѳBÈÿª³*k¢°ê¬|‘@CCCCCprrrrrøÅ¬…íÈŸ‰UËËÍÍÍÍÍ®#!„BÊâ‹‘ ™u, 6zôèÑ£G ™uÛ·oß¾};˜˜˜˜˜(KOYý^¬Ê<ïí'T·eØ}›Š{íÚµk×®üš|eÛå×Àøb\¿†—————ðE²€3gΜ9sà‹[ Õìù"h?~~³fÍš5kpôèÑ£G ÌqãÆ7N,._¾|ùòå_ìí_|Bù‹Q†!äOªÙ“R¶F ›‚Â^Ù“aÐc7~¿XveŸ …¯Ö Ô©S§N:À£G=zTÙ½"„Bþlµk×®]»6)üøê¹ÂÔY555555 44444TX ïga.6…—ÝÙØØØØØ”ÝžMíeD­Ý§¢¢¢¢¢ðÅ@]]]]]]ᾎ¯V/ÜØý"_ü¸|ùòåË—üüØý'[{°iÓ¦M›6,X°`Á`ýúõëׯøjÄBæ%!„¯cÕ;*»#„Ê3`À€k·°Ì/¶f(oÞ¼yóæpÃ#<ÙfBòg`‹|³ëtèСC‡•Ý;B!„B!? eøB¾[\™MiaUéØðŠúYUÖD=¾`ýUõŸ}_Þcö„»¢Uä~ÕùV´vþùùùùùùÂçe?ÿÕý&„B!„òkQÀòÃdddddd„÷e·ûøñãÇ//////aê Û^_____X²dÉ’%Kʼ%%%%%%......B•7öʦ lذaÆ š6¥ ßß»wïÞ½{¢Ë¦’°íE-VÍï?~üøñã…jì|õôôôôô„µÊ ¨mÞ¼yóæÍ€¹¹¹¹¹¹0îì|ÙÔ¡ØØØØØXa?¶¦Pé©/”†ë·ŽŽŽŽŽŽPÇÈ‘#GŽ ¼ÿþýû÷¿íçF!„B!¤T´ƒòÝX†Û¦M›6mÚ$T³kÒ¤I“&M„íX‰­sûöíÛ·o 9SSSSSSàÊ•+W®\&Ož|øXYYYYY‰~íׯ_¿~ý„ýSSSSSS…÷lê+ËŒ+‰‰‰‰‰Éï?v¾999999B@RÔùöîÝ»wïޢϗ­¥Ç¬lª2 Œ²À›âËŽÿ½V¬X±bÅ  jÕªU«VFŒ1bÄ!ðyóæÍ›7¦Ó~„òß²uëÖ­[· Þl­\¶ÄÃïÔ©S§N:Â’¥±Ìwö`ìß.>>>>>^—G=zô¨ìvl •¿m\f̘1cÆ `ðàÁƒ®ìÞ”Åî{Ù¸²ûfBù](àG)+Öàááááá!dþ±)½ýû÷ïß¿¿èýYæ ¼=yòäÉ“'3f̘1cʶËjåaÊŸET‘ŽÒç˦Ø~ëù²S:#’MfÛ±ëÃ2,,,,,,„µö¾{͇‡>|ø°ˆMHHHHH&Mš4iÒ$aÍÆŠ^B!'À`à}úôéÓ§Pí½²Öre—DeöýW±¤¥$–6}úôéÓ§ Ûÿ-¢¢¢¢¢¢Ê/òF!ÿUð#ÿiÅ;‹wï^·zÝêu+ Ã(Ã(ã7®õö·b_mÛ¶mÛ¶­u£¯«««««+¬õÇÖècj¥_…b¹¹¹¹¹¹B{lM>ö亼½ò2ÞXÀŒaÅHDyõêÕ«W¯D_ú|Ù{QçËzì|KÎØy>xðàÁƒ@Ë–-[¶l)L±f .\¸pAØŸUç­(Vl„MAaSxÙZ~,ÓýÃaÖ¬Y³fÍââââââhj/!„üÛ=zôèÑ£ÂßeVLŠýcK~”‡ÍÈËËËËË+{Pd¯ û»ÅÚ+oûòÿ¼ñúÖöØEQý®h{l\J·ÃÆ©ôçl UUUUUÕŠ÷÷gÚ¾uœØï†íÇúÁîß*ÚÞϾÞx$„üi(àGþB‚à½ù{ó÷æÀMû›ö7í<^ðhp²ÁÉ'‰$5¯Ö¼Zó*`ooý 7†ÿuBu^ooooooaJ0ãäääää$܈±@•(óæÍ›7ož9Xzг³³³³³°¨@ã»wïÞ½{‰>ž¦¦¦¦¦¦ðþæÍ›7oÞ,»Ý›7oÞ¼y#¬!( ;_vcÍ2ïDaÅIØù²ã0žžžžžžBàMÔ?6lذaC¡Ø ».Lé",¥ÿÄþ¡accccc#<ñ/ë`ÇcJBÈ¿ËÞ½{÷îÝ ÈÉÉÉÉÉ KM°¿{ÑÑÑÑÑу(Q†:tèP@KKKKK«üã²¥1Xz†U“/]‹-5Rº }i¬èËlgÇÔÔÔÔÔÔ„[冨ƒÅîÝ»wïÞ]XƒµÇŠd±5~E™8qâĉ…¿¯lûºuëÖ­[WhæØš¾,Àǰ~vvvvvvÂç¬X»nŒp]Ea3;Ø}Û^IIIII èÕ«W¯^½„)Â¥±ûC6C€=f^ÙŒ ¶Æ"›ÑP[ûøâÅ‹/^˜²þ°âc¥mÞ¼yóæÍÂWv\ö yРAƒ Þ¾}ûöí[ÑãÀî—Ø”b¶f4»>ì÷ÇŠËBH¥áù åççs\,ËÅr·õóÖÏ[?sœC´C´C4{¶öí¯nçÜι«ì³ûýø@“0ü“ûŠïÏß  ûó7rÂ÷|€Šãø©ŸÂvì¸üÚ?eû1`À€”=£Åqü 'Çñ7ˆB?ø)Çgnnnnn.|/êÿõX{|± ŽãoÔ9Ž`rœ¯¯¯¯¯/Çñ W¯^½zõê íñ3¡=þÉ9ÇñkÝ Û¹»»»»» ç;pàÀ ßóSfËöïäÉ“'Ožä8111111ŽãÿáÃqü"Û·zõêÕ«Wsœ¥¥¥¥¥%Çñ7¼ÇÿƒKh‡_ÔZ8Ûžî_é~mÚ´iÓ¦MÇWíå8þDÇOÕ®3!„þAÇñŽëÚµk×®]…ïù"Âß)S¦L™2Et{ìï½ŠŠŠŠŠJùÇç«Ìs\ëÖ­[·n-|ÎOAå8¾:½p|~-ZŽãAÂö£F5jÇñ®8Ž/&Æq|¦¢pÿÀî/X{üβýâ[ÂßC>€)ô‡íÇ…¿ãû÷ïß¿Ùöøâ'Â}_ôKh‡Prÿ PèÈÚyùòåË—/9Ž_kWØnñâÅ‹/æ8~‰a{v½DÝ'>}úôéÓÇ?8ä8~éa¼üýýýýý9ŽŸ±Àq|€’ãø½B;öööööö'#####ÃqüÚÃÇ(9ް í°×Ò÷¥ááááááÇR9ÎÌÌÌÌÌŒãø™ÇOí¶ç$ çÇf…û>àÉqÕªU«V­šÐ~ÆDÙñ2dÈ!C„öø%o„û;vž|椰ݑ#GŽ9òãÿ=BHEQÀüÑ¢³£³£³9n¨ÃP‡¡§,¦,¦,öý½ò^—d-ÉZ’UÙgýûýhÀ/ÚÀq|QŽãŸp– 8ñw7nܸqãÆ 6vãÇG ,X°`Aù$vÜ‘#GŽ9R¸1¬^½zõêÕ9ŽŸz,Üà—÷˜ƒŸÊÊqmÚ´iÓ¦ ÇÉÊÊÊÊÊ 7ðì†v×®]»víð+Ý¿ &L˜0ãtttttt„$_lC¸-ï|ç3…âVìÕÊÊÊÊʪâý`E°Ø} [+—Ï,ÿ<Øšr?[骽µjÕªU«–èíÙZÁlÍÂÒØ}üL a ¾˜˜˜˜˜ 66666¶lñ²ï-®QºhÛðáÇ^ñýKW7fÅØ*:l­AB©,ð#6iHCh&ÝLº™4ðBç…Î  Ê$Ê$Ê赬ײ^Ë€ÄΉ;ÿøá4U5U5UÀvíÛ[voÙ½e7€m؆m_ÙÁ¶(±x´Õ«!VC€&-›´lÒ°ø`ñÁâ`¼ßx¿ñ~@»¿víþ€ªŠªŠª PíFµÕn $H,¨ìÁ&„BðkÍ ÕG/_¾|ùòe€ŸÒXþþ¬ª/+¢¥     ðíýøÙ-Pû^l<˜Þ½{÷îݘ9sæÌ™3+Þ¿¤FÙÏ+:¾¿Zéb ß‹ëà34û÷ïß¿à3…b,¬ vëÖ­[·nßÜÒ×),,,,, à— )~Éá}éß +FǪ—ö³«BÈ·¢€ù»TATšÅ6‹m $d'd'd×{]ïu½Ыy¯æ½šIã“Æ'ÿöæC‡9 H“<&y €´ ¼S~§üNx[ð¶àmr4åhÊQà鰧Þh=Ðz Dß‹¾}XÝlu³Õ;r€«¸Š«e?–;)wRî$`óÐæ¡ÍC Ñ¢F‹-ê´®ÓºNkÀ0Ç0Ç0Ð: u@ë <@y€ò ZÓjM«5)‡Põ¿Yf½“OŽâ=&növ¨ìÞB~&£¥+µVyJ¯ì·Û?ªìÞUyYæ«*_ºê{i|±)!@xàÀÕyYuT0)Ï«W¯^½z%TS­lüÚ¹B† ËübÕ_E¹sçÎ;w~-¸ŠW)®,¥’ññññññ¢·g6~_!ã“e òS}      !PZÚáÇ>üãýç‹­ ïYffy׉e ²íØ}d錾§OŸ>}úà§—mço«Ò;½Þš'V‘¹÷b_©ìÞBþ‘8Ä Ñ]!3´* "&wºìfð#7E(Bh¾¯ù¾æû€Ä׉¯_‘¹‘¹‘¹@¯´^i½Ò€ä5Ék’הߜä!ÉC’‡J|ÐÑP€ ¼67lnØhÖh]²¦hЦ8pà€â7ÅoŠßÙ²'dOÒíÒíÒ퀤¤¤B îXܱ¸cÀ½÷FÜDéDéDéþuüëø×ù‡Ž®Çz¬Þª©©ÖúÖúÖú@ÃÇ 7| ˜-1[b¶0hgÐΠ ‘£‘£‘(R:¤t;*wTî(€k¸†k•}1~Íá•¿Ù'ûGä4‰ý× PÙÝIªcßÊî!äGd¸Ÿ) >¼ê1%ØÃ¾û÷nݺuëàäääääðk½•¿?_M^xÐÆ¦ö²€_ÔCÀ°)¥1üšs_uUt ¦t’/>õëljËîÝ»wïÞ-8Y&[éþ°óOHHHHHøjº¿®?:.|Q€¯‚+LÕ?~üøñ㾘—°=¿f#8;;;;;—-jÊ/ òkï Ÿ‹Êðdç'ê¼øb+Âv‹-Z´h‘ð9 <3üš{¿Æ$ÀUøbi€ƒƒƒƒƒƒÈWƒöíÛ·oß¾²Çç×üûu×÷g;f6ÿ~P§¦™¯ö±Êî !äŸÜØvûeü àݺµrÇЇÜW¶£€ùwQ‡:Ô«iVÓ¬¦I‰I‰I‰À5Ûk¶×l^{mìµH9™r2夰›Å(‹Q£HA R?¯;â5Äkˆ×”w+ïVÞ (CÊj£6j°`;ÀvÀWvü0Ì;“w&ï ð.þ]ü»xàõê׫_¯ììì˜â˜â˜bàîÉ»'ïž"ÛG¶l½pôÂÑ ú¢/*¨Q+¢V`5Új´ÕhÀÒÀÒÀÒ¨S;¦v  ·To©ÞR@½z;õv€Âg…Ï ŸEEÅJ¼Þ„˜;žß:@1K1ƒÊî !ä{\½ª¤¤XÙ½°Ì>fðàÁƒ®øþ,àÇ“øêñB ±gÏž={öüüüüüü„@ÊÀ(øX œDá«Ç ïùâ@×®]»ví øúúúúúþüqš;wîܹsÓ§OŸ>}Z81cÆŒ3Ð×××××B,€ºeË–-[¶”2ú³•—éÓ§OŸ>à‹Sý/ÏÒ¥K—.] ðUg…ëËcÙÙÙÙÙÙÀÊ•+W®\)|Ï~l -»Þl?¾Ê­ÐÛ¹sçÎ;Ë®½÷áÇ>ˆ>¿ÐÐÐÐÐP`РAƒ øêÉB?ØTa–¡Ê²nnnnnn_„F迱±±±±qÙÅ|1aê¶©Ú±cÇŽ; ꈈˆˆˆˆ_w}ŵÕûT5F_Rß6þÇÛ#„ü<©F¯ëf›7¶Ý¶ŒVþö?°z!=èA°v²v²v’—$/I^„LJLJÇZuµêjÕ:xvðìàYÙ-K¦“L'™N€ÚhµÑj£‹8‹8‹8 óêΫ;¯&­´vÒZ 0!0!0x>õùÔçS…'¤9v9v9vÀK¯—^/½€›]nv¹Ù8t é@0§Îœ:sêÃ,†Y Î9wäÜ`Ò‘IG&:?éü¤ó žc=ÇzŽ€ºœºœº «$«$«$¬1c)g)g) »2ìʰ+À:Ëu–ë,—— Ö<Ö<ÖÈ<—y.óPÀpÜŽ!„B~ðSWWWWW2Ù¾Ué€ è°",Æ2ÅX@† aý`V¢XZZZZZ ŸÇ?~üX˜šù«°€Þõëׯ_¿.ŒÓæÍ›7oÞ Lœ8qâĉÂvlMÄo  ~/(1bĈ#€¸¸¸¸¸8!ã²¢X “eÀ±ëÅiì|YMéft,Ó“]ÀcãÀ²|5fa?öû»téÒ¥K—Êö‹¯¡¡¡¡¡¡ð{aU†ù*½ÂñY`˜`Ùš¬˜ˆ¨¢.3f̘1cº=°*jUÔª¨¯tè^à+‹Wɪ’U% °Ùh³Ñf#Ðȹ‘s#g ŽT©:R€aˆaˆa 5NkœÖ8@ÙXÙXÙ¨zºê骧è@_©ŽG!„B!„üÍ(àGùé$‚%‚%‚¿Rì†0ÐmЦä0„·‹ ,Þ÷zßë}/ ½Zzµôj@ÒÕ¤«IW¸)qSâ¦÷†Þzo(••• œŸv~Úùiÿб‡xˆ‡t¡ ]@=V=V=°N³N³Nnn¸¹áfÀ¬›Y7³n€´´4 qAã‚Æ@q‚âÅ €œžœžœ^e2!„B!„òuð#„üq¤&KM–š ¨@*^͜͜͜;g;g;ç¯ìX„"y£óFçÞíz·ëÝ.àUïW½_õäää˜ð˜ð˜pàÎÃ;ï<"ëEÖ‹¬ <x$@ ñµÅÓWc5V oÆ14oؼaó†€ešešeP{Kí-µ·zÝõºëuÔeÕeÕe…P…P…P@:B:Bú/\Ä™œëÚöÒ>ÀgÁ¼[‹å€áÍç59¬ãï5g]åõ+S%K/K (”,lY4P{]cêráû¥SV§oívêüÙ9@xósýŽV¯ìÑ$„B¾Ž³àT8yà"ΤŸ®„õ9¥pÂx›45á(Påx5ùž€±Œù.óã@Ký´LuýõºVvïÿ\9úŸR?m§î^±£.íµí‘9:3Pš¤2G%h¼¿ES›s€Ë¤¾ë=²€ªóå?ÊÿCùøjO‹ãªúêF5ŒÅ±bb*ޯ߭ؿتØè³Í¶j[Gá<{hÏû<ïÊŒø48•qÎ+4èØ#¸›°Çcÿ¬ÃÉÀ>ÏàeÇ£O õù}ýJÐOJI¤«¿é÷vkÌ@‡Ê-B~®9sæÌ™38qâĉ'Do'&&&&&ÈÉÉÉÉÉBõÜ~ýúõë×OØŽü™X•ÛÜÜÜÜÜ\á:’7–qåÓÏÑí:p{×õ™‘vÀð§,_ð’šð$ûIö€Ax ‰âcž½fŸwh´ °ìάU>¦€”¡Ìt™i@ïøÁo†M­ì³«|+ìæ¶) ¼Þºîå8`IâV»Y€mv—‘ι_628 ®)— œ|r`À¾«€oÝ1©žÆÀÜk¼½¦ëqÁ%Úu}ä÷`PÐ*A~? ÐÆ•}¶„¯ìBÈ¿…x-ñZâµ€jiÕÒª¥z‡õë¬C­C­Cš5=j‹B…. B… =䥿¥æ¥…Í ›6²Ò³Ò³Ò§ãžŽ{:;v0ì °qËÆ-·£Ûn?º=¯‘¯‘¯¬8ºâ芣Ààƒ n´*jUÔª0T1T1T¼¼¼I]I]I]@þˆüù#@'…N ### (3(3(ˆòŠòŠò’÷$ïIÞä¬ÍY›³¶²G—ÊŦÂ~–ûìÿù0lÀü¾¦€N’¶µæ`ÇÀÀCš”ßN¡T¡S¡?/“?2ÿbùÛHô-Ø-¼2ÅÅÅ.@TS¡¿ðy¾t~Ÿü¯l_žbqN—kZÙ£LÈ×½xñâÅ‹À­[·nݺhjjjjjÚÚÚÚÚÚ«––––––Ð;sæÌ™3gÀÛÛÛÛÛ»²Ï†ˆÔ©S§N:À£G=zTÙ½"¿Ë‰}ûå‚î·ï\_©Œ4šÚ{ÆP`¤Ñ”ÞÓ‡2#d]e—ÝO¯ƒam£êÀƪ‡j›è§‹V½§9;ÈL}øV¿ì~ù£ò6æy\_΄Ó>gS‰–ÒíW”¨þ}o»Q/®H\ 4íÒR±õ6À6»Ëç ²Û±©¸Ýzåö¶ìºùv_\[wÑ9t7ðáñûFïî…É… ÛE§ ;–ȈÈo•· ¯Ptª¨sQãòûÅÆû{ÇIT{?[bwA××åçg£€!„ü!$"%"%"ÅŠ5kF+ŒV­Úº¶umë |¸3ëά;³€4¤! @Á¹‚sç*{t ù1{ûjwl ›+;U¶*Ð4ªÑËv€Óq»yÞ7›Þ©uo7c7úY?Ñí Ý6¶ö¤€ÖëÚþz—\먎'ºVlC»õ‰>_?jk“]æ@×S½ýfŸw¸ÔµŽ›Ð*¢Óäî;E·{Í&Êç¦-ÐäN›êÇiNå‘Þ1@=ÓèAýD`ö¼…Û—¡@ ù38pàÀÀÑ£G=ZöõòåË—/_.@Z½zõêÕ«—/_¾|ù²²Ï‚”–œœœœœ ¤¦¦¦¦¦VvoÈï¼dç.e êüjåíþß8%WzÌp™õ€ç¬I³¦Ír¿¬U’tÜáh‰µ|²—dÎÊš„kû¨AΛkoXŒRGG ±žæ.ÕK@sýúš€i ž¶C‡ û•g¯ó–Ú×N·›nÐ °Ü«öLñ`S×莞%0/kâ€qQÀÇ}ôÞeMoPcý;âØs·0“û`”:`•h ­5h0M=Jé)àÞÞ>¥Cà±Ü½{w·Šî—Ì:™á²ë´™).Éë+1kÒ¬©³€Ï‹ H_‘ž&³çK柰9zE㥅í›ÛèµÓ˜,»3súŒº_í56ùÝ·¼Ñü6Ш³Æ)•ÛÂùtµµ2o¬ŸÝ㳫E£ýÂ㯺tö³ÏÆ­ÅÂZ9:ÀD½ÁçúŸ^¦Ö}éó?JS–›„kùÔâ¯ÃHuõ  øBù]¤ÎI“:¨lUÙª²0»ivÓì&`ßÁ¾ƒ}ÀKÖKÖKØVc[m5€Gcy4F~®ù¹æçšÀ«Ù¯f¿š ÜÝvwÛÝmÀÑñGÇ,Ì[˜·0hµ¿ÕþVûèwÑï¢ß>C}†ú ºwéÞ¥{ á܆sÎ4Å4Å4Åi{i{i{!`hZÓ´¦iM ¿B…þ Àòå!ËC€Óº§uOëšb{QåJOÀö\»øV+©|©@)w Ë1‡!¶§„íwÚzð'<¡.s°£­ÝL`Á”YÒSKZîµ`Ù¬›ÀšQKºÍë_v¿©§‚E@§ó®wûMÝ´,¬·X>nÁ–Y©€iŒñqçÀ¼Ù‹'¬lòÜ®¶çce_B¾O5jÔ¨Œ=zôèÑ@QQQQQYñvŠ‹‹‹‹‹¼?ìïmi¬_Ÿ?þüù³èã³ïEµÃŠnïwoEÛa矟ŸŸŸŸ/|^PPPPPPöó_Ýoò{±Ì©‡CîäÞ> ÔSm|§I-@ÖZ®œï··×2¹ÃdÛ¦ „Ì6Q–Oœíê«T¯£p[¡pìUäë›ÅÀºŒ½“…w'F¼. ÿäúÆy¡0õ¸´•ó,fåþ/¦eLžÔÝÒ@®a'`ÖéÓ×è=. pxžÏdÜ{êì¢Üe‡pþ¢,-ô]6½9ð^â]ǬÀÊ⯂ä€å ¶ìi¼ÎIÕx錓ð¨Ù'Gt¦\×»}ÂúÉ ¯Ÿ½yÊ}ÇÛå¶kYè¹[x“V3Õ«ì~¬Gó­^·™/dZY9î½÷mÀi~Ï*n-…í74?XûÈB WóAJCJ;dAÿjS1i!`:˳Þ`fòòe«Ìï†sÌàX>s¦Œß8&ˆ9òààý¹eûuÝú²ùÅEÀ0Ãî\—µÀ{‰lÛìÀ¸´™æÈCá}¸qüjö•Àˆë®1ÎÓ€¼ Ÿ}ž\þïèή(ßë*À”‘ÃGš ´Lé8Ù®)0ß1 qÓI@,P,Nì/x0A?B!™4™4™4@}–ú,õY@ýõÖt]Þuy×åÀTé©ÒS¥}‘û"÷E‰$>þáñiÕ§UŸV)R:¤tnß¾ 컵ïÖ¾[ÀÌ]3wÍܘÔ0©aR8á~Âý„;àmëmëm 8&;&;&uoÖ½Y÷&Pƒ«ÁÕà111!`ØÈ¶‘m#[Às‘ç"ÏEÀú9ë笟„Ö­Zˆ[·:n5u(ëPÖ! pzáôÂé•=ºäou¨ç±œ“Y@‘dQË¢1€óG[û™Â÷íB[i¶(²ªWwv÷ç×ôcSn­M7 iÀòŽ…y7œ£dÖŸ 4¾Ñày}÷²ûq_2öN™%=-Ø0teŽ0vňñƒç:+ºÊJ‰ŠÀñ®§·œw¬ì«@È‘‘‘‘‘‘ÞKHHHHH”ÝîãÇ?~¼¼¼¼¼¼555555a{}}}}}}`É’%K–,)?ð–”””””¸¸¸¸¸¸ÕªU«V­šð:jÔ¨Q£F6lذaƒ°ö`iAAAAAAÂ÷÷îÝ»wïžèãúøøøøøÛ³`iŸ>}úôé0~üøñãÇêêêêêêÂùêéééééþþþþþþåÔ6oÞ¼yófÀÜÜÜÜÜ\wv¾]»víÚµ+[¢ÈÙöíÛ·oߨÙÙÙÙÙ Ÿ;88888M›6mÚ´D¦1;Öo@RRRRRR8‘#GŽ9xÿþýû÷ïÛÏ|£¬soW¿U ¿¾4Žh_Öžòýí±j²òæ ·ëo¶ðÅ*DÑ6Õó×w访µy/ }SA ‘¤U?ëÀ¼½ke6ÜOgG™wx’°Štâ’„0`GÈš+«ŠG·öü6®Ý:p±ïçç‘x©ú¤ÎVÖØn>ðxÜìnÊÀiýCwöïÝ?MWÝͺîÀŠÞ;ªÍ Z¶^ ´ rÌvŠFMu›>xý%ƒíÁªÛUo~¥¸ß°&¢'¦­9îðÔäÑø‡}Ù{Æ]ØZÕ+2Û!d&²Àå³›1ŽOÚ–mÏp éõÚ7í|½Iúí„ÏÙ”a6ÕšM}Ýk¸¥ÆÆ…€RûÅÛ tnmÚ 8ïîsнpϱdT3`í—ña.Ý?ûøôWþvùÄÙÝ}•›k5ŸÏ¹x èW{ø¶‘€êcêŒûÌw HÜxxÑá©Rœ&pÅ!dë¹'¢Çûùø8ãXS`Ìâ¾.½t„ô²Ûïjõç#)ŠvBù)ªŒ­2¶ÊXáU ZÐÐMÐø_d¸Ã%k±kÇ>ûp Èà2¸ xyúåé—§g#Ÿ|6x¨ÿPÿ¡>póñÍÇ7[–nYºe)Px¤ðHá‘íyÁ _yB)v]ìºØu elËØ–±@ãå—7^ÔíP·CÝ€Q¾Q¾Q> }Dûˆö@e¨ÊP•¡€|uùêòÕ±\±\±\ÿ˜½}µ;6÷:«tjÑÁàŠ@²@ò¤äTÀ)Èng‡@ ûqÁ× /\Ø¢ZWöI|EŸ=®Gœ½¬Áÿ»–Ë‘ó”Ëê„› 7¼Vñfàae÷™oÅ2Ü6mÚ´iÓ&@JJJJJ hÒ¤I“&%ÖÜd${{{{{{àöíÛ·oßr¦¦¦¦¦¦À•+W®\¹LžP½zõêÕ«‹-Z´hpäÈ‘#GŽ|óé}7–QÇj7nܸqã†p¾µk×®]»6L›6mÚ´i”ÛuëÖ­[·NhS6lذaÃwwwwwwaœ^¿~ýúõk`éÒ¥K—.lmmmmm§OŸ>}úTèû~âĉ'N/^¼xñb U«V­ZµŽ7eÊ”)S¦ëׯ_¿~½°½±±±±±1pÿþýû÷ï+W®\¹r%™™™™™ ìÛ·oß¾}•õk$¢&(`£Ã€ôéé2{ýýíʬ“.³(P,0Èç—–ùjXÍñD^€˜ŒØ9±¯¬i×ø±u§×eMÕ¾ªY@xv蔑€Cõî·z ®~ q/¸Å\7ÀØÉ,Ñü$pÿí­ÑÏ˶''_UÆ}™ºüˆP [º èŠÞè7¬ìöÍ Z¶Y-:£LwB-#-p Þ¶}}3½€Ò„íØþãÒ|1€Ç&ÏÀ1Ý0‹ÓËNšWB‡¦Èî}ÌOM>à¸ýÄ–›€÷‹¹]æúövܳ[ů[ðœó–ü¼‘y³?ók©üúï¡ !ÿ{ ¹rä¬üòå, £múÍô@læÃ £nLkèãÈÊ|=#Ô¦Uû-ý³Ã®z†ýLŸÖŽ0‘%ÇçuNjÍÔqÀˆ}=»ª›+œTˆÖ|Þ¼? >.##³þ»Ž•†~„Bþò]å»Êwä!yúÎúÎúÎ@ ´@‹’ZÃÖ‚Œ` ¨¸¨¸¨ø0õÃÔS7NoœÞ8ÉHF2€§gžžyz¸?êþ¨û£€èZѵ¢kËÝ–»-wû‡Â(ŒÞV_}|õñ@ ãÆ-ŒFqâÅæ+ÍWš¯ ;v4ìhhhJG•Ž*ª*VU¬ªXÙ£K¾ÕKíÔ}iùÀÕÔk›£|V—[ôl>‚Ï|SúJq—Ckw²qÁ׃ø"ZÀ(Å9…¢·“û²Va†J澬=_>œT¡Cò˱TéL=–qÇl¡¡¡¡¡¡B¦«öËŠ|0@DDDDDpêÔ©S§N (fÈ!C† 2ßXoìØ±cÇŽ -[¶lÙ²E(6ÂÚµ¶¶¶¶¶ÚstttttŒŒŒŒŒŒ~ßø±À `;vìØ±c@—.]ºt)±Ö;_aüØù²@hppppp°PMw×®]»ví*{\6> .\¸p!˜˜˜˜˜(ê5jÔ¨Q#aû 4hÐhÖ¬Y³fÍ„ÏÙñX椟ŸŸŸŸ_Ù㉋‹‹‹‹wïÞ½{÷îï_òmj¬V7¨yVxŸ‘ú6è€DØ}O{¬˜D¶GæèÌ™€yný« ~ùrvÙíµ\u6ëöpâŸÛU¯¢™¦µ H›™Ü-)Àþó™„% a€A0ãä(½áNN–ÛÕjð¦Á+¯´ Àÿ¿ÙT/R Q4 øÚ÷’:R;$þ¼i*r*l @gþéàÊšª}U×  àZÇ£`€¢~E£Šrk#.N –šùšÞXì?#fê{ ‰K‹¹-‡&‡êøÔÝPñë"uEzºô rÊ%ó° ¬ðô¡“EÀóqÊqšÀ õ§ÅqÕ€÷o²{g}ö+î[lR\bŠò+×uR|dp´ó¾dÊ|ý¸,ÐY¨_‚•¥×0<þh¿vP< ¾Y‡Úˆ/ ® ÌŸæk4å Q$ñ@"Xô~';Ÿó½P¸"1íú àÀ#NCÐ}HH†K®>ËæMËã«ù®CuÑí½Òx=*} ˜­°»úÅÊBþ l­=YYYYYYaJ.[ëŽM-e™~íÛ·oßþþqøüùóçÏŸ>|øðá`eeeeeUñþ”®*˦¾²Ì¸ò˜˜˜˜˜˜ü¾ñc盓““““#: YÑóeké?þüùóÂTeöÊ2Y@nĈ#FŒjÕªU«V­oïÿŠ+V¬X!pY{lÍ>6e›ÙïM¥&&Ç=t{u–šù†M·N<˜|ˆŠ‹Š‹Šö†í ÛøöòíåÛ 0L1L1LÎ ~¼îñ5àôO~²IxÏLž[¾Èn7¾'ñ`4ÐétÇ#m[“Žû<²7à½xŒñðƒ¢_LYcêe¡½ƒ(1X3µædõ–@NÕœ Ü:@¬ÙS÷ø¯,†}Áö’êÕž@ºú›~o'ˆîoédTce"!¿+Öàááááá!¬ÝƦôöïß¿ÿþ¢÷gÿÌoOž,ãÎÂÂÂÂÂBXkï[5nܸqãÆBàòðáÇúõëׯ_? !!!!!˜4iÒ¤I“„`E¯©nU[ T…]h5EeâZaî‘%#v•˜!Stª°sa‰û(µfÛc³]æÇù¢'ö‹®¾%Eý’prÆœ}W¢Óÿ¿=QzÇy3|* Ÿn,nüXa7§íLIà½ev﬷¿îzýlð#„B*Q•[UnU¹h»j»j»M›75ÜÚºµuk ÌÝ7wßÜ}À©Þ§zŸê <Ú8ûÔ,C`eÊ›”µ·Ï¡vÇJT¼ÙÝ´÷7Ty¶Šhº¦Ñ# ÞݺVæb@d‹cnÕ‰=÷w{Ûù)ïðp8Ûã²{ÀoÖ’Á«€1“.ú„®G<̆9µ›¬5Ú#úxªo•ï)'ï'-ómæw]hÿ"–ñÕ¶mÛ¶mÛ !QEtuuuuu…µþØ}lênéWEEEEEE¡ØEnnnnn‰¢N,£->>>>>¾üj¾,p% ˜1¬‰(¯^½zõê•èïKŸ/{/ê|Y@oéÀ;ÏàñÊ!¬£:xpS—õG„*µ~k'Y?Ø$w˜lÛôK€ÏLØŸ(ûÎáé\[wÑ9t70ø€ssÇ`¯áÖ›üÕa~2sâù@Ÿ§1`Ô¸ö)³‹|ßþ‰¿n\%u$wH† Ã7îݺL(’2Ôןs0Ðãi›U-öÓ×ÿ`¬ÁÕ:SûÈí½+ë0Ï­_ßr°Ð¾Ò$åÙ*%–Êñî<è¦Ç!ÀVgK¹†€êw÷*©Ïí¿88vÇõmÝs#Î žÌäÆ>¥ìYsyU1 o^ý–B=àS—y”=/ïsÌ$ |~<>è×ÞþeûÂõÛØ}éØE‰ïØ X´m˜Ô¸>ÐÁ±ó®—Ê76µyŠÏ|«E;€ì%™³2¥•šs-fýEEü(àG!„òÅÞ>‡Ú ¨½®±Gu9àtÂ~^‡7ßÞΨµC‚û—ø‡ìÎA[ju˜ 3uöõØ®²Þý,³PƘﻴÃjUàj«ÈM7|€½=·ÖZ× hz£ÑËv¢SÿŽ…¹ùK`à–~M{­׉ñt °«ÿÞe‡¸òûIÈ¿Y@@@@@€P×ÛÛÛÛÛ[˜Ì899999 4¨eÞ¼yóæÍ2YXÆÙÙÙÙÙYXÓNT ñÝ»wïÞ½¦"‹¢©©©©Y"SèæÍ›7oÞ,»Ý›7oÞ¼y#¬!( ;ß‚‚‚‚‚‚ò׺cÅIØù²ã0žžžžžžBà-/////¯l; 6lذ¡Pl…]¦tÖ?†e.ÚØØØØØÓ§OŸ>ý+dX±v<¦ôñÈŸIû¦þ ƒ&ÀþÃaû®Ìƶ›‘7ËÈÑÿ”úi+pÄ#¨Çn) ¬î颓€î— ¾%‰[ív:‹[l³}( ½NfxEªªY1î½÷mĄ̀^;ËqÀšUó?ν \8u²é±6À€ £»UVÖÝY¨.ºIûýœ¦,TY¼È:÷võ[`i¡ï²éÍûöËí½ 8TïÞ¡Ç`ÓÑ଀* U5«.¿Ÿ?ŠU>|ãJ§ÈÖ@w-÷ñýòµ€Pÿ“†Ç×Ö…9‡îtnê4høl\»u60Ùg¾•ÿ޲íÚpÕ}&ÐèKû‘Ö—ÌÃüˆ+aƒ/ª)œW4.ít(øËÚÎÀ²Û³¦Ï¨ ø­›d5!È•·ñ³'°ïpØþ+s€f­ŠZ¯nš];ñ•%¬6¶¹Ún$°±ê!ÕcÓ„q\©1·Þ¬\à`Û§¶Ù¶Ù]÷8ë2÷M:"@+ÊzTÛ£íÝÖ}íZvRŸÝí³Sxpñ¶îÍ{¿þºý(1Ž+ï™!„BþÉ“Éùž;Ný}úôŠ‹‹‹‹‹mÛ¶mÛ¶ ˆnß¾}ûöm!“eš›››››––––––B»sçÎ;w.0yòäÉ“' JÖ/v>,óoõêÕ«W¯ƃe þì)Ô¿ZPtPtP4зiߦ}›­–µZÖj0³çÌž3{6Wl®Ø\dúÈô‘éóýÇ©3²[ê| Å¡fOL£Ñ†Ô·¯ì³ÿù²—dÎÊZï1 ¨%x©ú¤ÎV…zIZÙ½#䟥½®›mŒ0÷¶Ü2 ¸|~{­qc=eÕ²ÛS†!„B!ä_kæÌ™3gÎ444444„5þbbbbbb„›r:nܸqãÆ kzyyyyy ¿ ,X°@¨[ËT;}úôéÓ§!C† 2Dx±þ°ÕСC‡*ºÿ¬=XckÒ­[·nݺuB»¬hÅĉ'Nü‡êî,ÓÙ˜0a„ €K—.]ºtIL†‡‡‡‡‡ [·nݺukÙö8p@ÈÄcxìUEEEEEEWècÌÌÌÌÌÌ„@&›Š»cÇŽ;vÛ±ñg™‡,@ËúÍ®¯ö÷ú˜‚˜‚˜‚áýï+ÞW¼:t:è²}eûÊö\õ\õ\õ€èØèØèX ¨gQÏ¢ž•Ý{BHe¢ ?B!ä/B~„üûP†ß Ð-[¶lÙ²eå¯ùGþ[vîÞ¹{çn`€Çß¾ÿð°áaÃﯯ vÕÚUkWÄÚˆµk#lG~”áGþ|”áG!„B!„ll·±ÝÆv€¹“¹“¹ ÞV¼­x[ÀWÌWÌW H“8&q €B|ÆûÊîí¯'©#µCê"`¹´i@³@=^ë¡–_e÷Š_CòÇ› „B!„|¯ãIü냓Û6l-ä6\žqYþ;âÀák™abƒXeŸåœOéþ—>ÏòÎï[·ÿYý¬ G¦L™ ï»Êw•ïú-׿¼qÕ¯ì·Èö˜Šö§¢ýøÑó©èï©4¶}EG?¹½¤Œ¤Œ¤ ðÀwdø‰â?øð[ë·Öo- V ÑOº>`зFát}~ÛŸw¸?F57ùÄê-€8…ó9ôªì^òkPÀB!„JôîK%Éç­ß$¾É$ïÞ+ºSÙ½"¿ËG»ví9+9+9+ vWì®Ø]?¡aQ¥?ÍßÒOQ*°üÎó|_å}•÷U~ÃiH5Ï¿äù¼æS6%4úõG%„üJð#„BÈw+çt¹¦ÀÇóB_‡zË9• ¼0Hü<*:%9hv½Ñ¥†¦€çºÁ7ÝZ)šnáâéäïÆ~¯ÏLâ-_d&1FÇkÅUv¯÷…üël¥) §V´&Ñ~ÿ!ñˆÇ¿p­4òsìܾsûÎíß¿†Ÿ(} ûö5&®œ¸râJ O§9O´ô5ÌÍÌô\þ ¿K®/gÂi§ßºp` p)ð\ø™÷@zTšTê  Ê‹ªšÕu·4kØ p±w÷ëŸhÌÕÖYÙ½ÿunê²þp&âðþC+€=+ÏÉ…^©ì^‘oEkøB!䛥«¿é÷vÐ&Üax÷@—ÓnkÊ';Ÿy¡/ß·`¢ýroZ>°Ðgy“5y€y\³=m/×­£=n)VöYÿšV×ìt»l´'d¿se÷†B~=[?[?[?àʲ+Ë®,ò­ó­ó­=Ïö<Ûó °t²t²tÄÆàžxÊîíïS Xà]Ðéã<˜ž4²Ñ°Þ@xVèäPà½DvÇìçÀÓü'º›ò–Û-é8¿±–h’\·¾l~qQeŸÅ¯óÊèeÝ—>À£fw_Þ>PÙ½!ß‹~„B©°"É¢–Ecdz=Ž{´®[Ew½ýX7b™áyà•êSÇ»=€kMCZ{<1ŽnyY¸juvÔ3@ª@ò”ÔT Ë)7¿ÀÛ­2m*û¬ÈETó›mîÄVv/!äçkhÓЦ¡ pb쉱'ÆŸ®}ºöépnƹçf-'´œÐr !!QÙ½­|‡Sw­ØQˆ’¿¢~i0Lf¹IAÀ•úq½Ò#í"oÔ.Œ~k ì=«}á ÛB®­œ/0-ɳáP7  Uþ‚ü~•}6?ßðØ‰“7çjÝ5{<½²{C¾ü!„ŸàpêáÔéÀæé›§ožÄÊÄÊÄÊŸµ>k}ÖªìÞý<›FìŒn7¾'ñ`4°hÒœW3¼€ëÝt HJ\•XSv?ëðf~Ï×.2T3ëgé=·«íùPñã³)™ßº}žlÞ´¼¸o㸠\ÏŸ}Üß=.ì<+z¾jÿØ÷¥Û)’(¶(rÝ>!„ü)ÄäÄäÄä„÷º7toèÞvì ØdËgËgË·®Þºzë*à´Êi•Ó* ŠU«*V•Ýû?WÔ‹+—Æ EêÍ2¡$ýäG/K\6¾l|Øç,M!PPP =,=,= Hl’Ø$± àîéîéî (¼Wx¯ð¾²{ù÷‘Y';\v=ð9"÷bÎ<àíØ×/^Û—¿_§.½zŒÖ]Ú7ðP0P»›Eú¾e·Kiœ°íE40N¼Í>9@3OÝ5— ¦©G)=ܺ·ïÕj6peÊù£gSDoõïuÀÀN~öYÀÎåë‚W¿šh{ªmZ,¬•£ãÜì{-+Ühê©ÓS})°Rcn½Y¹åŸÏDýAg=NN·› ±l&ìVjε˜•+´'JäðK-ÃWa¶ê@ã÷Z+jœlz&鶦¬6kÐ2àÍæWï_ýÔñ}9[Å7Ï:ïlæÜаܫöLñ`S×莞%0×a‚±ÉÀ{‰w¶Ù/~ׯäïG?B!ä'h,ÓX¦±Œèïßy?äý`ûá퇷œmmmYYY@2F2F20u3u3u|ÆúŒõ D4‰hÑȼœy9ó2ÀYqþ\%¬ÃG7šÝ²¼Æáh` È|–Y(cRñvċĈÃÖHïW 0Ž5¼\+Gø>§jNPn u¸ãp×ùÀÎA[j¶õuí ¬¾Buá{ îCóa¦.€÷ÊCæjVM÷žÓ¤üãw;Þ·×Í€Ã)Ûí €K-Oí;t vjf?X1qÝ…Íz@Ã{­êÚ§OÌcG?ëê¶óñ¦3@À—©Ëçí ¯Œ&-÷mêYþqûìrgtàìü HÐ~~½°lÜüC3Åe“ÖÞÜh ŒY7é¨Ïβû–ûìÿùÐöJçN=ºÛ†ì¹±o4à±£÷W1`ðRþú÷êZ™˜¼lfS¿ëÀØu“úV Ú§Ë±~öCg n×ת{msüñþ4`ù¸[f¥';Ÿõ½PðZ;eÕÌQe÷g»Î§ÝÖFoi¿«#ÐgO#ÎcMƒWÅ,žt8ߦ°eà³pÞ³ÅFÀÈãßNS(¿®G<̇;÷ë¸Õn\h{ìå>q`åXÿ™³gBœ/^F¯ŸtÑ'TدfšúºÞÀùvG>îÕÄŠÅ’Än½öºÜê(|®ð®ºŽüˆŠÿŽ !ä·YõXÔh[£m¶•Ý™®E½ïõU Ov.lôo—Û®°ýõšG+«ÏÇÇÇ~%CNÉNe¬J`£Ô~qÇö€²¦j_ÕáûW†©u_úýÚÙ¿lßxÜìÎË;€á‡'®™º˜öÑK§²Örmå|€1KúºôÒ.œ:ÙôxÑýM¸óì=°Mmõ«5÷Ï%£š­ûÚ·ì¤4ºoeÔbÐd¿MÓ–ç€ þ' ÿCåýO©Ÿ¶áY¡SBBÛ«Î+]6bÄ2Ä*0ó‚*=Çô<îÒÈýóàÓJÀ»ÿœ~IÀ ô±ã_ëœCwžczwé_6Sqí‰ó® ­¦ªL\ ˜ÕkW0ëôŠékt€ž«4t8¥wèÎýÀPßnFƒÿ½S©6ªÒK!„üZ5jÕ¨°[±õÚ‰Û·?n?0ó1Â+Ú  ÚÛ þ$kyî÷œ_¦J–~¶P˜U˜TXèlÑnª¹ðS{°Ñs»ÚžÀÃz÷ÇDû\·^è±ßùÓ‚/U†aúÕÜ÷ ³ÛXÝoÀ­‡¡›úËöY ˜?¬=ÙdlÙö=vôžà*LY0îõ¨V_><ÔU0K6]ìÂÞ­‡d+ñ™t‡ëï~¸i3 óY¦Ë—À¦+œ >¯Zk¥k„TùçÕ;Ð5¬ëb`êüñq£k˜à Ð=;¹4}“;¤È3ýæO[ú˜d0öƒç @ÿ¹ž¼ÎL`óðŸƒB{ <~< Øã¶yéšI@ï@×#Î7y0ö÷­ Øé9oü<  ÿ—€aìí XÜ«co¦]¶½öº<ë| X4qNìŒ÷&ògÚÍ'6psÇž÷nAý¾;:(’, (R¦pêyTúdàâÁ+©×$CλÚlÚ t;ÜyD§46øÀ`xè À0Þ ƒ^.à;ÂOf‰àµÒsäà)€Ù#ÓùÆ_ hw?ص¦ƒ°d¼_ø6°Úôp{Ë=‡:B€¸@º oÁn@&_&PÆh66€'öN,ÐKЩ£}hÒ&׆_ËêäÏüBù³YmlsµÝHÀ/h­Ì†ÛÀ"¿©S·+ çÚÎòVb.fPî¤:N5 h~­ÍãvS€®uÜRúͯµ~ÜvJÙv×É- ¬ÕIã àz k¾cŽèí'.c<ü`ÉýÏy…þÃZ3íB[i¶((ûyõ/^Õ>TkQuÐìzãK LDg0j¤ª/Pë¼VOï÷榸2;Ý&¸Š‰þ¾çþno;?¸/™rçí.^.Ñî)§scCóÔšSÔm· îa]ÿ!ÓsÒ¢±ê#V ïOv>ç{¡†èí;žoû¶Õ?Tá3~jx×@ È—É™ÈV|÷þý áûãΧ·œwÆK#­æ57 Êêf×Û˾šÆ0,±vÞù/Sxÿ¡ÿÜ¿Z÷ ”„@_¦r–bvzù×…BÈ[g·^¹½- ›¼‹é,IÜj·Óèz·wX?Y@êªô4™=Ài}>Ãlø'×7Î ß>£ó<–]kŽÒLâꬨÈgü¥ø÷ßÞjý\x}8äÎç[góÜúõ Òf¦¸$ ¯Ÿ½yʉˆ@#Óѱó.—IÉ’aÀÿ“µ¾–éw^ñX¿#}­|½Iúí€:[È5ìTþx¥Jš´HP{Zü´е˜Ï””^'3ü¾ÚXØ›;ˆûg‡\õ¬"ÛÊð#„BäZäZäZYêYêYê@Ú­´[i·€çsŸÏ}>xÜüqóÇÍÛ·3ng×v_Û}m7ð6èmÐÛ c1c¸"­¶Xm±ÚèTÿÝúwbÀ˾6¾÷dýžñQÎPNPÊ$ŠøŒ®×gÓï¼õþòe×júÿIÒMŽHµŒžÖr0xˆiн»)z{“X£Ëµ>•Ü?åÚË€¯N|RÉPNP*Ýžx±x’ø @å­r%¥ò·+/îP<£üóÒOÐÕÖÙøåÍÆ²ßk'kºiH@¢^Ò£—Ž_¾¼üå¼,Ãg™zŸ1u±wb/EÏ8ŽÐÃ;¼’6$祲©IOÊn¯”¥È)4ÝžTä))þM P²Ð¦pŒðýóZ âIÛ¾¬}øh[8ÿÓ¢Ý7ðÿ–âNÕ|µèõUÀ >‡ò[û'uRòKv…’…-KöBù'²Örmä|Ûì.mœØŠu3|ä¿wïÂÝ*ÀJ ~m»ãòûÕƒfõSš.kfدë¦ç¼[˜•“™ÜB$®YîííÑáŸí_òÍ›-üZw]ŒM¶ ŸËÉW±¨2¨r¼šLµž¢«~Wq¯’*Ð\¹Í’v½ ‡N =¶Õn*f ÄTÞðЀ9À}݈%£–hÇgÒ•ç•á˺/}G@;_’A;€ n•Ý^ÂQâ„ÄM 6,PºñŸ§ìLž +l7³î˜Ô‘FºT¶žúê«Þxö£Wÿß‹~„BþòõóõóõlÇlÇlGàÕœWs^Í›%6Klļyó¸³óÎÎ;;ë½®÷ºÞ x‘ÿ"ÿEÉŒ°‡xˆ‡%Þ— äv4ìhذëc×Ç®`Ùò‡e@÷¾î}Ýû@¯Y½fõšõãç³Jn•Ü*9`Øþaû‡íd;Ëv–í $O^$çÏúsÿ÷¯ø—µÏG7¸Rß ¸nÝõÖÇ/™_¦J¾¬x{¬øB½{uíÍ´ÅÞsoø481NñÕW¥Ëo§H¢¨^É"ÒùÒRüš.m‘Vv{‰"‰âÁ¿oÜ„~òUa!"D[º¸†d¡äU ~Ê´KÉï+^%¸X·¸)1(@ ^%½BŠÏ ðµíÿßõSÿöócýÒMÔ©£µ 8Ûñ°AชﯼX)[ñ þ7•¸lÿÀúWPñV !„ÿ/£múÍô@@ðâµ –óq]/‰ž¢Ë˜çÖ¯o9X39ðÐþÉ@;7óDãÀ•)çû}Ø99«vãt%€ã‰º½€¡ÇGO¹:ˆÅ –ßn±‘U{€xýû¯W¯D5ßwÀ®š§Û T¿Ã,Ë#;BÎUn1€¹¨„»º¿ü!„üŠæÍ)š¼;óîÌ»3@zÓô¦éM¤ô¤ô¤t vgìÎØÀýž÷{Þï DUªUx°÷ÁÞ{K4€”x-E-O-O-°>f}Ìú00|`øÀpÀlºÙt³é@­úµêתh¼Ôx©ñP§:Nu µ@jÔ‚è¿m‘m‘-€Y˜…ïø­HY‘²"±pÄ ٵ²ke×VöU)Ëùˆ£­ÝL`Úâ9r ¥€ƒ=Žªœ4zîëö¬ó¥ò÷¿níqK‰ºxâÊx@%H9L‰MMmè'èikobk?íüÜD$‰ (Æ™>kõ¼ €;ü{íM7M(L¬ìÑľPN< Ô‚>ôìÊ~ÿ¸N¬ÏÓ)nóï Ÿdýo»T!Cð~ýGÊO^~—þÿ8.­ŸWð€ÏÔNÑì­Qê÷ÒMÒ¶Ö¼Üj|wÃý­€v²f’†4PõcU‡*_Yå‘UÅ=åtnì…| õåvVç!„ò_$3\®»ìbàðË]wwÔ޽̺‘õhžØ©‰"3BÖUv1 ·¶ªa•órPC€j½äª·ª>¯–#o¼2|Ù#Å0H77ù(º½Çr÷îÝÝ ¤È$.IÔ-4kµðcçÙSš0ÕöÒý³OsÀÃÕ· o5 .g™¤&±æ…uªV¼ÝšñZµü¾¼é$7z±íù?"Ù”çéIž†ö:fwÙÓ-И©}Y›Ýÿr¯å^ÊÔOo"Þl¾èöŽIì«ø0^b¶«Ž  ‘« ª5ZÃBÈOÁ©sêœ:ðîлCïñëâ×ů.7¾Üørc`Ë¢-‹¶,¼Öx­ñZXw·înÝ$gKΖœ ¨D©D©DfkÌÖ˜­ìöÛí·ÛŒ•+;V84p(PS»¦vMm`jæÔÌ©™Àí=Ú{´kÜ5î$nHܸøö!íCÀqÇqÀë^¯{½î±?bÄðõóõóõ\«¸Vq­4|Úðiç€FŽFŽFNù>F¢ŠD‰*€¬‹¬‹¬KùÛ/[¶< È­•[+·0NkœÖ8­?7ÐÇŒ\;$´P#]õ„Ê~`ôú‰a3Bèf·Ü ½_¢ARJÊpÀ=pØ./W¡ØÃd/ÏIÂvN'ìævx ¼ÔNÝ—–p;bt¢èv—LY¾~<þ7uÕá”íÎvµ*{”ÊZ7f³ËŽ¢¿_5~ýò­·é<éé¶@§Ó¶kYr\ìçux ¼Òx==}ÔïàÀ#‡ÿy\6ŒÞ;ž´[ÕþüœŽóý+’,jY4X4m¥Ìº½¢·_8c¹ÉšçÀÀÝ#'N^ÕL•¾ì×õ‘(’¸/q(*t*ðÿñö!„ü]ª¹É'Vo´^dçÜI I>Þéhg`¯áÖ›ü΢DæÙWÜÔeýàÍf~ê­õè¶GÛ» E6Z¶lgÜ2¿v&¸³+Ê÷ºJÙvXµÚÙã. ›l:a •-½LúøŸ'›úÛ2¹ÃdÛ¦ÀEœI?U ˆX{Ñ9t7`ÐÍ·ûÒooWû¦þ ƒ&€î„Z- µ€“3äì»*ºjî‡ó[Ï>N¿?|á`‰‚ -“;L±m à2ðØÖ~eþraM¿ÒÂúœR J:J:ªD€eÙúeë—­<Ûz¶õl șʙʙˆG<â?¿+jq¨Õ®Í›|‡s=Ö»+Í£ÛßëÜèÒ¦ e`öØt­ñà¥vÚÆW/€Ó±çû‡=>Ë~žö9X=zñòyÓúw,¶Õ)‘¡6|ýÀô~Õ€wƒ¬Šu†Ïð²"×ÜXuk`k|Ü0N(ÎqÆ-¤ØsÀ;‰/ÞaúÄø†áÅÊ¥²ÎvºÐöÒ> Ëi·5šög:\lë„Ø^T½Ò 8î~úàùë€ßc_£ÉÏ€éªÑ*2ÂþC7ö—íÓØ~+°Ú~g``ý‘C&¤7ÖÞÚqwP;Æd·ÑEàŒCˆsØUàT¿s3C^Ë= Q̽¾^µøgéØãHô¾½}DIDAT·±À¦ð~çù6K]W×^ÔJÜ‘ÜhyÅzhS? ºÉíZ÷vÛ¼wߨ7è¥åò¬K ЬgãZ «ýúë úVå¾ò `Ç~¯àëÀ§MŸ ró§Í4šü PÎPJT¢IÄò¯7}ãâØeý'Uî§Ý[øW›ŠI s×]ý°hÛ(¹q}@ÒQò„d43çÁúû“€ç~q‘±€† š{Y%Ý5=Æ Ë`ô–éz¾­€p“Ð󎞊=½»uz; ÕžhÎÕÖõN¿?¬t`{çáªúÀ¼ µ2ëÛRÙR)RÇ~ÞyÚ{ºŒt LÒ|®ÿ©ŸŸï6²{ö÷·;Qr®÷üHÀk›{ÝÞ’€»‹Ã²ŽÇ€.n½NõÞ¼³ÌêõØ“´aPÀa¼Úôµ·éÔß.)^ð¸5rê3`׋€ÍkR€ÁŠ]½[Cç.þ@FÛ×7_[{Nmª¿Þ ¨uÄä©éd ÇÊþrƒÎ˜ ç÷ŸÇ¿ü!äßB RrçäÎÉd¹d¹d¹i2i2i2À‹Ð¡/B'ÞO¼Ÿx·Mo›Þ6®=¿öüÚs =#=#=ã+ínÅVl-û±…§…§…'Ð÷pßÃ}õêÔLœLœLœ]1]1]1@íŒÚµ3€ò6åmÊÛ¾Òþg|Æçïgb&fVö`~?Ÿ•>+}V±^±^±^ÀHÝ‘º#u¹r#äFTvï~›+VC›úwŒ¯.8÷X6qMúÆj@h‡ËŸ"†á-¯ŽÎ¤ó¥%¥ÜÖ—ZØ5¯LY8îÚÈ›@ë‹6Û¬üʶ+›+;U¶*pQéÄ´ÇŸ~·ËÜŽÔ8Qd)ey÷01ÞkøØ4xUÌâùÀ`oõÞÍ+{TDÛá¾~éŠ"`Óˆ2vÀÄå>]ç}ôtêhµ6Y¹zÑ`ˆ_Ù>2e÷g™¡ŠÇü÷Ÿ|çÏ]ò8ÔóXî©, S9kH¶Æ—"&NÀúa+¤>†y XÖï7ÒXÆæÙj‡OÚs/2^~Øß:xÿñ6ÀÁžGwœœè&j[kÝfÏœ6Îû.0eá¸Ï#{èùµ ø?ß‚)3kL¹ LZî«à º|º©JŸá€2”Š”þà [B!?‡zWš«€Ã7®6мl_±úýÊÛ_ªì¾Â-C'‡¬Šúv.l è:Ô:ixWgæ¥9…@?ÓÛFu¤²¥–• Ði©z¸ò\Lè`ÒüÅsïÛìØn :xçw .˜d™N–¦ok¼«ÐQ·ó™®†?ÿ<[ûÛ:Ûkr UT èn7èR«6 ¯nTÃXìÚíkײ“°n¿óáÝÀz¯E;^VÌ™³afc@q—’²à(ÖC­g/`Ìäò3“qsñ[â±B;q|âx Æ4Æ4ƸûìπÈÕ‘«#WÏ;?ïüüÖÀ2Ø`°Á``µÎjÕ:ÀÒÁÒÁÒ¨Ú¨ @ÿ´þiýÓ€ú(õQê£@ÆVÆVƶ²Gé¿‹íxî8õó´5@ˬ̋IWt³3¨ìÞæX·SçÏÍ\Ž÷ë5d3pÅúÌŒà@‹«Í'6Ùþãí“—«W•”ttC¥e«–Ю7aìº;'„üFuFvKï´8Ôì‰i40úÂú¶Ñ Bþ R^×Í6F˜{[n\>¿½Ö¸±€ž‰F€òWŠP†!„üd…A…A…AÀûêï«¿¯¼ñzãõÆ H2N2N2âžÆ={ Ü[yo录@”m”m”-p_ö¾ì}Ù  IHTß©¾S}´èÔ¢S‹N@ÿæý›÷o˜2;ev ¨åY˳–' ¡¯¡¯¡(=Tz¨ô;%wJ®DJ¿È©¯þð­qE!„B! øBH)EÁEÁEÁÀ§1ŸÆ|¼5zkôÖH‰M‰M‰ž®xºâé àA‡t¢ó£ó£ókÚ×´¯iÿCÃÏñÏ…·2­dZÉ´l>Ù|²ùLÙ1eÇ”@ÝuGÔêêêš4h>T©,RYTó­æ[Í·D»ˆÀ×RÚ÷c?öWöhB!„BùÝ(àGù×ád8NÈ©•S+§““¼\örÙËe@|ûøöñíGyòå·‚oß Â‡ ätÏéžÓ½Dƒ©HEj‰÷}Ð}„·ÍíšÛ5·Æ  Xh[h[hÆ÷ïßtê,ÔY¨¶Tm©ÚPØ®°]ákSúú£?ú—x-;ð!ä/ ’¡œ¨”X‡7ók|P^]Uþ}e÷ŠB!„üWPÀòÇÊošß4¿)Ñ(£QF# ­mZÛ´¶À‹Ü¹/r'‡Ÿ~r¸=èö Ûƒ€k5¯Õ¼Vxÿ:ÿu>€Ä ¦DƒÞð†wÙãÔµ«kW×èíßÛ¿·?P¿aý†õ& L˜,tmtmtmµwjïÔÞÕ÷Vß[}/ å-å-åý'ÐMÐÀ` ÆàÊMBÈïÄŠš\ÅY€û•Ý#B!„ò_B?BÈ/ST·¨nQ] Ó)Ó)Ó xýéõ§×Ÿ€Äƒ‰1cÆ îªÝU»«\¿yýæõ›À³ gAÏ‚J4hDØ€ ØPö8z;õvêíÚÞi{§í AÛm´j[×¶®m ègëgëg5kÖ ú*ôUè Ȭ•Y+ó-Õ«¢*ªBdàB!„BùPÀ"Ú—5à²ü²ü²ü€ôéÒÉý“û'÷âTãTãTûÑ÷£ïGQ³£fGÍ;úîèí<Â#<úJû_ŠB¨´Pi¡Ò°žg=ÏzÐwKß-}·æYæYæY@­Ýµv×Ú hôÑè£ÑPRPRPRªT¯R½JõíµC;´+ñZÚZ¬Å·ø!„B!„¿üùxïÿÞÿ½?ðÖã­Ç[ E%E%Exõ,êYðpÖÃYgÑ£G7—†/ _ú•†Ìaó²Kד®']°¹gsÏæ0Ùe²Ëd Î®:»êìŒÜŒÜŒÜ­êZÕµª*WU®ª\ª%UKª–ô—ƒäLÁL©ìQ$„B!„Bþð#äÆùsþœ?#ž#ž#d*g*g*©×S¯§^â}ã}ã}Ç 7|ܸùêæ«›¯€ˆmÛ"¶G|ñqD‰§a¦‰>^Sï¦ÞM½Ñ £F'=-zZôŒ«W3®è\ѹ¢sP¢:Eu  ¨¨¨¨¨X98QÙ£I!„B!„ü7PÀßàs£Ï>7²®e]˺¼šñjÆ«À‹/¼hhoRÞ¤¼I’7&oLÞÄuë׸/u_ê¾pãüó7ηïݾwû^Å£4Wi®Ò\ EX‹°a@à '4œ˜›™›™›µž×z^ë9 ¹Fsæ@©“R'¥N€œ»œ»œ; &/&/&_Ù£E!„B!„¿üÈ_åý§÷ŸÞ26dlÈØ¤tIé’Òx&ñLâ™ððìóÏ7½nzÝô®^5¼jp±\,[~û’ž’ž’ž€Í› 6€&¦ML›˜užÕyVç`´ÚhµÑj@Ë^Ë^ËP)R)R)ä5å5å5X–•=J„B!„Bù/£€©)ÍRš¥4RÅSÅSÅø³ñgãÏÇ<óx ðíÝ!Ê¢Q€áã¨`û,Z~EE,š>\®À5¸ƒ]Ü…6]„Q“à.¬þ4q`†‘9Oç£×è5zEô޽cïÑ^µWíUDñU|_õwý]ú•Ÿ#øñ·ýmÛG´—íe{Ѽ6¯ÍkD£l”òÓÓü¿?HäǧþÁü Áü Áü Áü Áü Áü Áü Áü Áü Áü Áü Áü Áü Áü ‘oï¿ðdùñÀ%tEXtdate:create2013-02-01T15:45:16-06:00E)%tEXtdate:modify2013-02-01T15:45:16-06:00b¾••zTXtsvg:comment×SpOÍK-J,IMQHªTH/J,È(ˬR(K-*ÎÌÏS0Ò32×32040424Ö3051UÐ@ájr)p)„d–ä¤Z)8––d8çç($¦§[)¥àb\ A©Y©É%HbjÊ&¦Öjé%Öp™àÔ¢²ÌäTljRÁ%‰E%0.·5’=ù7trtEXtsvg:titleStart->AuthCompKÕÔIEND®B`‚keystone-2014.1/doc/source/images/graphs_authComp.svg0000664000175400017540000000570612323716267024000 0ustar jenkinsjenkins00000000000000 AuthComp AuthComp Auth Component AuthComp->Reject Reject Unauthenticated Requests Service OpenStack Service AuthComp->Service Forward Authenticated Requests Start->AuthComp keystone-2014.1/doc/source/images/graphs_authCompDelegate.svg0000664000175400017540000000702012323716267025422 0ustar jenkinsjenkins00000000000000 AuthCompDelegate AuthComp Auth Component AuthComp->Reject Reject Requests Indicated by the Service Service OpenStack Service AuthComp->Service Forward Requests with Identiy Status Service->AuthComp Send Response OR Reject Message Start->AuthComp keystone-2014.1/doc/source/images/authComp.png0000664000175400017540000004141512323716267022416 0ustar jenkinsjenkins00000000000000‰PNG  IHDRƒ›ˆôÓgAMA± üasRGB®Îé cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿÿÿÿ X÷ÜAÍIDATxÚíw\ŽßÿÇ_í!¥=”¤Ò6BFÈH¡dÉ !2ã#[Ù# IVH©Œ’ì²JIK[)í½ç}Ÿßu®~úøòùˆ»¸žÿÜëºÎxŸsÝç}s®×9i¿˜ ¦L7˜¯¼~ð:ÀÁÇÁÇÁ÷«­øý`f03˜€_®_®_.`9Ôr¨åPv[EÓÙàdWÆÏµŸk?×¢k¢k¢kØ] ¿›´7ioÒ®N¿:ýêtv[CÓYa›cØÃ»‡w/p(ëPÖ¡,vWCçç¢ÍE›‹6ÀÁêƒÕ«555v[EÓYa›c0¨4¨4¨|úúôõé ”?.\þ˜ÝÕÑùE(B,8»à삳Ôy)+)+)+v[GÓYa›càqáqáqvêïÔß©Ü ¸p—ÝÕÑyø˜ú1õc*0’c$ÇH޶×%J•<Ên+i:+ìš|dñ™ë3×g.@UJUJU ¨UªUªUð ¯ðŠÝÕÓñ(o,o,oºñvãíÆûõp>e>e>e€¥ˆ¥ˆ¥»­¦élp³Ûy†¼>¼>œ5¤!¤<´<´<”ÝV±÷%îKÜ—Põò½¿qÛâ¶Åmc·õ4•ÓcàÄ;ˆw°Mw›î6]à¦éMÓ›¦ì¶Š}4…6…6…w–ÝYvgÙ¿/tJè”Щö·‹±‰)Ǭ¢~ÉpâLÚcÈÒÆØÖê—†½°Û3}É'çOΟœ /4^hÙÏ„þ}úŒÙŒXæ_?¡ÂˆÙJˆí€Ý=}·’É•;¯äÔOÈç7£Ã:†;ä¹C±>g}Îú»­é8Œ*U:ª”ðcáǵ½^Ä[Ä[ÄÛþùÎ;·eõ% B2Fe·Ê·ñdÓÆBÖû9 èEHÐâ§£bª©ë§Ý®Ý|©BÈ"Þ—s™¿c«ú¥¤¶OnÓ»ŠSrÔ±{™ÿžÐ3mã%¬úx=o=î„íÏg.„,°Þšé5‡üëžœÕ%$ítVH‘!Oß&¤ô&¤o†¹à>=BNE_ù¢»î^ç¡Ã:†úîõÝë»SOÀЧO+ž²Û*ö‘§˜§˜§HÕS’)É”üuù~oår(†Ëé¥< 1z·4ãÄBL¯Øá.AÈyfà”×·ÈßOè¨í‰êYI„Ø\s泚J'׬ðn¹?!«¶íßtÕ™:^¾ÓÑ»ˆˆ¤øÆÌ)ÔžEÖë¼èÒó„¬ã>4ÿº!ïÎ%¬Ê² dõüº×ºQábsS^ç,#ä¹aäÄTmBʳª–ÕF2'ySÓÅ)콇‰3ùø%¼Ÿy?ó~6+nVܬ} úô‰ÝV±¯F¯F¯FÀm‡Û·GGGÁÏÏ· ªäsÕ @ñ£¬•X>àsmþ‚‡ÀµÚ#£G¼ÚU`Þ–Iaz£gYûÜ©YÀ@~ÍÇ=t‹•ÆL]õ–†»Жnv ]Zâ-è9¹zHO×Pc¢‚6`qÐÈPכʇW‡GŒÛ:¶ç9¼àÆi òUM¯úé@|xj³ãÑSÞ!+Á¶ÛØéèðŽA±L±L± Û!·Cnð!øCð‡`v[õëxí÷Úïµ`6Ñl¢ÙD@|²ødñÉ¿.VÃÒœ¡üRƵíõéÙ†Òýäÿ¿ËAoµû)¡W7›¼*À…çA/ÂP¯Yi¾»Ç2ßKpPpPp!‹«W/®þñô: c=>ö8!aaa춦i™‹ørÒ‘¦cÐiCÝ¢ºEu‹¨É·ÊàÊàÊ`v[õóÈïšß5¿+U^F#ŠÅn«~œªý5'êg2ùÂê^„¸ û½ •a·U4_ÂöÕ•ÿnnn ŸZ?µ~jÀ¬øYñ³âÙmUûsDëˆÖ-€wï,ÞY€Ý6»mv´"æÑéCúôé=== ppáàÂÁô¡}v[÷ã0âñŒx€[›[›[(üPø¡ð ¡!¡!¡Ánë:!_J¬[Þš° –„œã‡=ï§÷ó í¤¨q©q©q’ œ œ ÌnkÚ^\xq“&L°ÛšÎK¿Ë“Ò5»•âs_Ÿ³Ïî"äµK´WúÈ_gK‘’iZÈEß¶åDXð(B>nýìPt¸ýó}ùö}¿C~\áÙáßJ|C–‡,Y®z®z®z춦ýprurur¶rnåÜÚîÎ×K1­˜qdã·ÃýW¾L¿Íù–Gì5ƒŠ@—+ø®PáâÂÓœr‹¨·?«þ¦Åžã>WtžhÖk´z»3ÝVp¢ ´«û>qûö«'V¾®Y—„ìÄöˆèuyú#í¤Ô^ª½T{‰šœ«ºPu¡ê»­úïäWçWçW·šlÜÍØÍØýãé¶S­q=íGSŸy˜YO7•µêîN³$É.=¼Œžl%dEâÞIþÜ”4škÑK‘ÈRTÞ xáñ Çš¤ü›/Þf°Ž,Éó—“™#š\rYJÈö¹n»‚C ™®¶ŽûL!—Çû…¿¤Â±ìe)0Yk–´úïò¶ä{Èý‚õ£5”dûzÓ£‹ï—rÝ+¡„®”=ž7ßèQÒqV=²`õh¬Çn;ã•NˆyÄú~熒ׯhM…UÞ­'ºÝzLIÃg­ýkîùg„¼­ó)’À‹O"£K éÙbÛþá„øÝ‘û–º_;{ž¬¹FȲ©»–^©#d¡êvóË É¯,ΪØö¾vZÇÀÂþ£ýGû„øùûùûù³ÛšÿŽË —A.ƒqututud·5u"õ›bqc}Á¹‡ÔyÖŠõ‡®1­ãk˜GÈ 9›SÇŸýò–)²tµÓõ+©+oИKýqY°Ve²¤ÒeŠÕ5aÔ éó²u‹E(‡ÃzËÁZåÉ‚%µzb.çáDBÊ9*oÔš’8%}I^-!öoÇÜð¤˺œÃ27äÛÚÃj™ÙyÒ¥Ý ×eÉÊã;ir`È2*)é7++ß%ÎŽU>Tzqa©;s Ù8ÙånàUBÕ¿)O’#Ä‘Ó=àŽ).lZ¬T†!5):U&Rõ˜[FOëc¨p¬øo{^yXLHêý,žÂ½„¬íuÐûºîºÜÃܨ,Böw;·åÁbêü þwÓt q õ¶ÊKˆßñûœ‘ Ôu¶oíö£ØÊÙÊÙÊÃë†× ¯,>Y|²ø@ŠPd·u߆©ÉÔdjkÖ&¬M ž@Á¤þÊù@ŸTÕÙÝÏq,ÅeáÿW,FM:ó9ÐÖSfÊjñ†i&¹E€–žÊ–p7J±i–a¢#3…FòßžÙDK©Ô"{¦K†]Kò ªŠy+÷Ql¦#޹“—z(ÒˆËK’c L:=j’À5›3‡SH ʘP°P­èa.•Ä奾ÎMtTût¯tAeki¶Êj¹àùâÈc)~€ïÐa«©òé]×ÎW|H‡oŠãû4H2'ºð²ÿ{ù}ÔÄÌI…2€ù!c«þ@œpÊÛ[@§A5\ΟŠÿ85üZòy !®‘·i?U¾ú÷ ƒšò€~žj ݽ€äp›d%ÀÂκèÊÇo¡Ì§Ì§ÌtYÙee—•@RzRzR:»­ú~ÂJÂJÂJ€ ªT'¨’ü’ü’í0n/§¦/ͯT4nI6Qcû σ^¾y@­qˆËoþã÷sTO”ïMÅg5zÕŠîrÀ¥Ë·¶‡l–O7ÓO®_ûpÊl@0˜¿Ž÷ ¥§²CVHbå«Þã–dÐäΰf®¼öJ­}`)3µ¾<Ç…§:溆š&=´©ó±|)Â99€Nƒj…œ\³t›WXjjΧ?Ÿ’`ëÔ«–ËÉ3^‹îïÙ\Ž[ ¿£z—åkiårr@|xšSn1UŽ/ÃiK«m½fƒµÖ„U¯+î绺hˆk,a¬ÜEü"Be§Ý+™†»Ç¯ô5} 0¬˜±Ì€–žòvY‰VÒõ/òe)?×ïŸ=¶ U>UÁv’;€)£Æõ=pdrÜçhõ¶¦Ó;‡‹.Ž¿=þöø[v[óý8;;ÛT·©nSe·5mÑ2o^#áûþÞÑÈ`‡ûˆÛÆ—7§6çªAÆå¥4ÿñ¿lù©¯›ŽJ¹œ0–w°°Zp òü ‡yÀfñcZAA@9ge`­) æ%¼Mp -£:TÎðdN} ìö=zïÀ3‘Û’KŒÊWàÏEÊa4ÞnºÂ(¡ +ß¿ía=¹¥›[Íõ0í¦÷8³ñºÝ«+€õÂmY—çÅ[ÊëGQ“„TÃûÿ(qõÇùÍu½„d„.–ó^ÎYÞP}¥Ù6œ†«Ò4™CÀœ;&ƒ†Ç||tžlÞ::ù¦è/Ѭ¥Æø)×hÖëx-¸~Øapräc ñN“/£¤¹¾º „f ªòk§O^ zÙê´ÄtÿðyÀ®WÊ÷¦óo¹s)¼Å_Ç{ßͯËK`þ³áƒ¨xNÇð5jkkA A A  Ú©Ú©Ú Ü&¸M° ƒ “ “ “)5)5)5€111à|Ëù–³96šß“ß¦Ç  . . ¬ \¸&¸ëy×ó®'»­ú:W^Yxe!à²Õe«ËVÚ!Ðt,~›‹Ôù©óSç£'ž @¢@¢@,”,”,d·u44Íü6=*gUΪœ¸l¸l¸l€ûû”ö’ü á¢á¢á¢€Ña£ÃF‡i‡ÐQˆ¶NÊÌž $®N¿‘¿ÝÖ°ŸßÎ1€<àŽ8q:✰>a}šÝFQìNذ;Øn¼Ýx»1»­ù~Ú[Ñøµt¿©tloZƒn¦~–ÏÅay!wþ~?!ŸÎ»4?‹îînJIXcUcUcÅ>{ ïÞ+¼GÙӔєєÁîZú~¬¤\˜HÈ–»ÇgÞFmÖznØ´W×)%K™÷åš–†uÝ¡ßѵ7û´}KéÈÂm¢ï¬çb„,ÊÛñÆÛ–R*&‹g$å3¨p,áKeU·iì…HB ï–ZT #äqJØÕ¤s”RñÌÆëË_^¡â³ìdÅŸûhó틱„”ެ^cÄî»òóøm‹•+V:rÃå†Ë öÙq|ÄñÇGâ¼Öy­óZv×Ê÷ÃR*ê•Ìþph2¥4d5|–C`Q_r¶ò.!Ëkö÷s¤|kF(ºvœ w»0´w<µ¹ë÷*YÊ@Ö1 ÖîÕ1 ð¦$¾ãŠ–ö>ÁI¥ÏÚD–µKuÉœr§êPÊa±¨m(nZNˆqà27~jSÙ·Rqû?MüïßÏè,tzåã·°3´3´3Œ«Œ«Œ«€©Ì©Ì©Lœàü)æ+æ+æ+`eèÊЕ¡@~i~i~)»kåûIpþXW3†Uj”]v ¬à žè‡§§ð•5ëu)EZ>¸+æ%R'xxîÙâ˜>6X¬£Ô’¨ÐtªÉš±ÐÒS¶•â¾Oéø¤gXMÒ9 tn¹Hu`³9_’Ét& €8³ÛÔ.cŽË9f¬mÆÉó<·®ñš ˜T8®å,1Á§?õxg’¦è(¨VȽ¦òeéÖyγãÌÑÞäyñ05o¬w_[ÀšcrúßøKi¿ßÃôîß»ïþ@£U£U£ÆŸÆŸö •…o¼ðv0¶dlÉØ@*V*V*–ݵòýÄ姼εôÖäV Î³usîšÌ4ŒRÔéµì¹8ÓΘ¡«N)êšN1¬k¨øA6OGÇÖþ{¥£ ›@Ÿ*°0k겡QT¾ýi¸Êû5oÛß»eWé · âJÉí@ÀY—U6À Æã‹ÑK[ ¡(å¤\+‡t ÒsÐÃ< OªêU¹s@ÀÙ£«l,€+]ï(DDü¼9—ŽÂoï 1ˆGeŽÊ•ܪݪݪÛ+Š*Š*Š*ÎVœ­8Û~Ùï©ßS¿§ع|çòËÙ]ÿž¿¥¼2ªCäZIy§çÊô“n^ ySFmÚúáZóš Mó^¯d]éÙÍáÜEü#Be¿»Œ ô¡”„š-ÊÊïU:ZŠMÐpðZ\>Xh¸ýìå +'O¦TPT\)µñpÀm•8ÀA÷躛}õoœc.ã†:ª<&Íé º ñªž$pêë`ªÁœ°Zu&oƒ¿óá@eÀôž¯Î¾N°ÑÊÂî±Ì¯¢Z­Z­Zšü{vëÙ­g·1=ozÞôv×B e2q‚ýr¡“¿Ñ;¿¿ýC±Y±Y±à›ã›ã›C7˜d0É`RÛð¥ƒJ•úñ|ý|ý|ý|C -<´àràràr`wm°Ÿ¬7ùÑež€¢¬•è/ø`̈́ݞég1­rZå´ÊoúËß“Z'µNjý÷|™BL!¦•^Þ¨¼Qy£Ø]44ÿŽßvŽáÈû#ï¼ÿ÷ñ Ïž/<ÿßó°ˆ°ˆ°F›Œ6mH‡H‡H‡°»6hhþ¿­cP®8\q8ð*çUΫœïWWW÷ßóÝÛ}o÷½ÝÎ;w:³»hhþ¿­c`1Tv¨ìPYÀÛÄÛÄÛäÛáóøóøóþÃëÌÛÛ[ pWà®À]€þTý©úSÙ]zšÿÆoïXÌž<;ØR±¥bKÅ×ÃåŒÈ‘3âß§ïîî0;`vÀ àúÀõë»KMCóßøc‹]§wÞu˜˜21ebJÛëÙöÙöÙÿb5&™L&“É€í;Ûw¶ï€yó8æq°»”44?Æo·Ã÷RS^S^S(H+H+H%õ%õ%õšÐ„&€p.Âõít"^G¼Žx 4ïV <³zfõÌêÛñhh:2\… ˆ ˆ {$öHì‘V¸Á nò‡ü·ÓÙ?rÿÈý#§§§€o‡§¡é p͸®y­ø´k÷‚Ýì6‡ Œ°¸l×»¦w0çD²`²#þ±ßÓ~}®Žƒ¨i­â5ã"ãp½)¶)® øK9Õ65ˆüJøÎJ×»– 4z¯;Ûí,ýÚõ#ÍОcÝ|B²¶:“#¡Ã:#4ëØmûˆÎ¯>^+ ôíÖÅN 8ðsUµ ¦YíW­ æè:é_g×á©Zú00øœ.m$Ñýo>ºÿo5Öb·PôÀöÀ`ÎßÇ¿Q½¥Â¾j³P«@¿\ùóøcçhhh¾ÎoëÜŒŒ•á "¤ûÏˇ•>+?šßßÎ1¸®s?6à%q=G§ýG´Ãþ ¬†ïnwnì¥q@±DIßÒžÀAywb©üêùë7Õ'³»hh~ŒßÎ1œYr±Îç1 ^$-šœ]r)ÿÊ¥¶Oôo=é¿ìq<û<ç%7`ç¾þÝ–D ºKµOöw›ECÓ©ømÃkýð•‘Z@‚VÒ–”€¯ùyqwe O&EÁ hò3Z­•ðŸ rkTÛ'=Ë!°Îû̹jpXxq……}$_ésŸáC¢ßÆÊ¦Vû7,ö\9dÃI k]÷½+€Q/L–ÎØT WÆUuÀOåÑÐü¿c8³äb÷c`äS}ã!“€1 ºègÆ÷ƾeœZ~^ÕKä¿§~¾›¿óê8]>æÅ›¾ï,ž®Ü­>-7Ëgz¤™7ð^çÅ™@¨Á+ÿ°SÀýñuŸÒ«-i: ~'Ö“Ø¿0@òÖQ ž¯~Gƒ5 Ð$}EyÐdÜ4¢i-Àädò0iÊéŠ1B¬u:-¸:Œiš‡@ê:'“#“3š?tÇÅàŠå¼è…**ÜØG‚Ã3þZþt~m\Íû&×Öº×v,úP4¿'¾Çà=÷ꂀ듓كèïú>»'ÛòÄÎâ4Þlzò /uYòà±ÌSòrÐ¥Zp¶`<•N¢FòÜ´ÑÀC£‰çmóábpÅ´8ÀGå ÎÌóÓŸ<"­†„£œ#»m|ÂIDðߎÐд'Þ1°†F÷Ǥtt¢µÆkÈj ª^Ê!Ôï ÿÉ&¢À……Þ×üú¢C"ÀèÞ˜wöÀèç“&˜OnN¹ãÿ` R&",Üê»:1Z³4½R{–*Ónοx'PÕPí]=˜Ýµ@CÓ¾´‘DQZš•Ån³hØ Kù˜z^ÁK‚–Dÿitú MûC;š6ÐŽ††¦ ´c ¡¡iC»9†Ú‰“ãB¦ÈÏbPÊ?Ù¢Þ·û_í”ÙëJ/6úÕÔ¶è'öoqé}â#»­¡é,ü°c¨©Èª<†L–ŸÅøëøöñ«O n½òvmÙ2vƒà¼áx„Ç0ÀÅÞíú™ÿ «b ˜\Læ´ÿno{¥ÓYÒ¿<ÏoÍ7À¶=»Ÿ*þyvÑüf°^W>} „0¥¥YYßÿ{aŽû6—Lê“l™²ñîáimÃEk½<õð!5Yˆö~KlpÊÄ¥fÿC`ù)û´Í•@6Wâ„È}09»K4•JÈ–›%Ë NÒƒèÙò9¾¹ mÃZq~ —&Û7þ^Âg ªtvü @-Q5H9òjÐ¥e@ß(M­l@7²¯N9ð=WL«9‰®•]õ…ÎJi=™=bÅ¢eݤ¨ëý¢t4µr±ѲnÒÔùZÚuÕÔ1WW(×q ùÉ ˆ–4§£š¬ü^IHî6òc J7&;N¯%ÝlÊ>–½ÔN¨\"¼çб£Òçnäævú¼×ªÉÈg5׋:þºMõÉ@œÎ¤ëÀ§žYñŸMQ¡&³Ì—Ï ^ù…¹…’E#‹õÛÖg·2aS@%¹×{%Q@>KÎòŸÒçdr²Öx4ßpglki7 Í?ñÃŽaÊ #ãí@s×Xqj}ä–D B/ªW´plí)—s‘À wûw››z¬Ð7Zg¨&¤žb–¦ ¼¶5ˆ]7x7 º*v*0øÍÀ§ýÕ¨ü¾¶á{¯³`M‚úYÞdE-׎×N<˜t Ðü ¶GõÐ÷}³ïûÇ~ˆïNÙDz7A3É.u08làSÝVvr2939þm‡zbo/•§€ÒGÅ®=¶7ÏÍøE+NØÜ˜Xã²|áb™¸qLÎLŽðo§ÏÅàŠáºÑ¼–„9HWÎàÌ<÷£wæwç‡ëIûhôÍl_. ºKÍ•m`̳IC-‡6+8µpÚºeÚ`Á9«qÀ’S ê­Ôe'¦Ì­&Ý™yb?`ôx*Óò5°àüìo•®K]Ú¶ÁYOôëæA¹wâ€Ác3LçÆ÷ÆFZßbW9°îð Ã%Ÿ€Y>Ó"'{cž™ ³H­•`]Ÿçi¹hÆ¿øx.‹ývÖn:ØÜ6¤‹U_ô{ú˵àÔšæ!Ž‚Ç/ç׃nê Q‹ÈXkBhhþÜZ 垪^"ÀšcN;'µÜù–i—ØmUǃ^+ñgC œhhhÚðÇ9†¥'­Sæ–Ó=šÿÅçhhh¾ íhhhÚÐFà**ª Àn³ØÇé–ݘæ;6ÿòg·E44¿nñSø§œöUSªÌØmû 8zNä|0°†Çj¦UÐÍ›ÿ4ß¼»³@7ÕhU0`·%4¿–6šÝ†tºv)ìRdÉ“5‹‹‹e·U44¿zކ†¦ ´c ¡¡iíhhhÚ@;š6ÐŽ††¦ ´c ¡¡ií::=`ŒmcSŽYÕö—iÅŒ#Ùmäσ 'Τªš_C§ÿÚõïNÐ’§£ck€Ã§.\zTH ‰Ëw}K]—"=_ô4pEN?ÀnkÛŸSŽÞ»y X˜5Åvh %Hÿx²4߂ݛNv4   )Ö.Ö.Öf·5„ìt–ÿþ@H“C–QÙ~å§ùßÐ=†N|Xªcn`?±û CVØðõðç,T_koÖÅÌMÔu«ßÒ´°;i¹`äZ`°‹ŽWÏ‘Àl=‡è o%ñîZâes-ó>1z’Ë7–õ°0`´×âwÇÊýGWKOŽ”.v/vëŸñ3^»ÚÏ@ËÆ´Ü¶Ü8]€úÇwšâ€øð´Y¹ €‰ìˆãÚî ßHž+€”˜˜|×›@±G™@õàꦇEU³+'Ž8(¨.Ϊ$ Ȩ,Ø8.R0òâ…Ós÷æ¼|öa#Q?6SÈö+è^Ö þQ×J¹ˆ[œú&ǘ2uLaßã÷l®'œ.@ˆ]x`ò$`ºð8™~u€üÖEÓ–Q"çÞr@/òûeÐo%:(ñái޹E€¶ŒÊPY÷o‡çòáÔæ8@ X\ú°ï{ëæ®|ï¹@\^ê›\[`@oMîT8‰ Ýü…^©‰™“ ¹Ñg¡÷ù™Òë»}ü7«ÅîC§.X?Z lwÕ ʹªk'ꮽ¦Ib÷Ýøó —]½ìš††î1ÐÐÐü´c ¡¡iíhšaIŽ;Šô¸£Ùóü-áîäÐŽá#ijÆÒü:àýŽ$ÏÉÔyE/ã'Û€g‹#\Sý=ÑÖI™ÙsÄÕé7ò[Mjî>xúä=KJÇÑÞ¼÷þÓàã™ÏO‹Û/]›ëŽÃ¯¬ ÄJ4+oþôêûiÐŽá7ákOª¿YµëŸòb—E¶ Žh¿ä ?”ž«º H•ˆ}èÚ‰¿J œ:8§Dü#^È/ Þ;¤ÝȦ3ifõ°f@`ÒƒA`šÑZÓ³:@@£Æ62q»€É!«—x(›O,4VÉ„)%mËõ›¨Ciš4€´³YO‹SÛýÕCÏq…i¹w€‰ºÃ{jm¬³¦,œ4ñ³ ÞOX“5`lbÈ1+ÍA‹k.ªEн¥8)»Ö$QFnÐ]9Hѳ`+0FYϼ÷B@ꉘMW% œ'nþ'àÎÛÐñC€Eç:m¦îZ›tƸ ×ÓKΛ/u\E½~­¼R“Zÿ8ò—ø ; »…Ô‘€שÀ»“€´3ŸŸ  q%M+€UÃgÕ”VzÔòñá©Ù¹E@ÍÓû±5ÀðäI¸M²>0îý§×ÀâÐÞñ\T|–¬øóo¹s)(3¨QkÌî»òÀn…UG££(YJE½’ÙM&¤j͉úY„Äò¤tÍÎ&d¡êvóË ©ðñ%g+ï²¼fÏq?GB"’â3§P B· C{Çs²ŽûÐüë”bpÞ¹-«/YPáXÊG–Òñ{•¬íáÇ-í}‚“Jÿݹ„UY„Ä_M–»êëÊÇú؆â¦å„.ópã'¤<«jYm¥@LÒÍ虿™}÷åOV>vPœ?VçUÆŒa•å@—Ý+x'úáé)|@¥@Íãz]À>·YÑæxb^"u‚ç^‘ )€écƒÅ:J-‰ÚM§š¬k-=e Y . EøTøÿuÑc“Î|δõ”™²À“ža5Iç¾­|äxÁ±œc6°±ÁÚfœ 0ϳY`R=⸖#°ÄtŸþ< ÔãIšN[å#¯6—°Îsžý/`Žö&ϋyc½ûÚÖ“Ó‡˜²ûîüþÐC‰J\~ÊkÖ¦­ ­6OíҢЛs×dæ a”BOï­v?Å!ÀÌ–ÍZ92›7M§ÖŒ5Tü ›§£ck)奜ìqK²‰Ròyí þЖQý[ô=ÊG—^Gž4½WJnꬲ±n0_Œ^ 4ÞnºÂ(ùºò‘õ}Š>©ªWåÎg®²±®t½£ñûìwÐÑ¡{ Öš™fúÍÒàl¦çÊô“ì#¿»Qܼb³"­ßm5`n>îPW@ÄOè@/`¥Èþ§W»‡KòâÕÒxr‹MsåDYW€#“c(G°‹é‘zïã›|&[à™ÈmÉ5Ð*TV•åÔÄzÊIß6,=r; àmxûìÛ @E½‡Œ¤<0WÐt¥Þ`ÄÃM*S‡‘GÜì H¿ÞŒSê¨VðìåÎæÝ¶·(W¾Þæ¬Þ̰Zu&°þsL€ 'v¸«`zÏàNÀ1œÃžc'»ïÎïϧ|,ZS´¦h 0Qt¢èDѶ×#ßD¾‰|ôßw|ßñwwwu}㨣6ަL7˜nð™vZ&'Z¬xå~ ¸sØ­Ò¶œÝFÑtTþ¸ƒDDD‘‘‘_âK|Û†‹ºu/ê^ÛóC‡„ gw)þ=Yoò£Ë<E;Y+Ñv[CÓÑùãz ,øð=à 8X:X:X~;¼xˆxˆxP4¸hpÑ`€»KACósøc'ͽ̽̽¾?¼“““ h‡@óGðÇ:†^õ½ê{Õx³f̰Ûjš_ÃëððØûpïý¿L´«hWÑ®€¼°¼°¼0»¦¡ù5ü¹Ž¡‹={,ö|ýº“‘“‘“qˆCœÝÖÒÐüþØÉÇ¿éŽîèpäpäpä´½œY’Y’Y(ˆ*ˆ*ˆþûäih:#|ÙÈF6°;bwÄîê´°…°…° P¦P¦PÆn#ih~-´chaæÒ™Kg¶Ú«o—ú.õ]ê” ¥ÿœ, M§„;xàs³¸Û€K¼×ªv›Ã>È(íF"“¿ˆ×+Ë|›±ŽG±Û:öÑÇMmW÷Á€ËÂõϦuâíÐiþÜQ†‰»?wÒŠ²þ*ìô¾¥ì+;„Ýf±Oл?}Ç_=€.²bÜ’.€ì6ŒLz$ðþ à²p=¦±Ûš_FIôaâØd5œÝf±È#A»Ma'îU?:$#M5—ƒÝÖÐüjè9š6ÐŽá7èqÒ`îgeª±ÛšÎN»;†„Ô˜'Ñ.À¼¼‰OŒ¤ÝÍ2oÄR€Ñ4Ö(—[‚W(.5Jrм‹z²»ø_§aE½G½-eïáŠcdwƒ^Èo•ò%N11ydY§}L¤â5ŽlØÛ0¸´àä™ãŸ©t~6g"\žì› ¹—ݵGÓÙi7ÇP,^x¿°°Dy:sò €˜À(mÀù† Kw4]>'xO½bŠ#ú¿ý¬»² Ò*•zÒýì'Þ¿MÿvÏkïýý€»¯®û]uÜžú.¼~ðô0ó©/P’Sè]Øسô¯Þö©x!änþí.€sÔŽÍ[µ€† {ëç´y¾»ÜV¤7‘·“ô4*Í¿¡ÝýSn׊~e–¥EÀ¾òSÏžúÖ;9¤.:öัÀ†»ì}D] ÛöFHiH˜÷Á ¸ÓóZ”¿ o©œ¥0X?ŸÇ*0¸¬vRI°=mñršPå[©Xñ’ú]Ówž¶%0ض‡¹Ìa`Já0îAÕ@´ñÛ™au”}_¦¿~ÒˆyÏQ©ïêÕÌhrÕH¨ÞR)Ty\,ÓUæ*Õ üÂΗœY ¤&‹&ɧ†\SÜÙë©äÕŸÊg;Y»\†:5A}r ‘ŸZ˜B€z#ï}Fõ¤Xå»=éj¦ß*«|¬zÐsW°•öFËkÎQùÎõ1÷âùúý(ËåÉ]ß쪵 p±ÔrÑzz¨Aó}´›c(\•Ÿž7è*¨#¸/–4–ŒiNÁSɬ—:uœ»=kZæIê¸Æ¬ª¾Ê˜£¶Ìs…!p'!⯘€foxñºop ÎK¹æ¹È) & £ì—S{ô§Ï4_lÙ·BhÙ?ì°Ô*ýóËÇ>zÍ=€÷ëׇñ¯–>ñÄrdÛ>;;»j×&©&ª*û,ð&ZèžÓ™Ünq8,œ8ŽéœÌ£ŽŸÞM<š&”Þ/>V,LfXF[Ia/2Ÿä9Úgû ˜\¿wyëEE*Þ…GÇŸ»2€øÁï?Gùw·¾›ç¬PÙh¹Åˆ=ö®Kä ª'Ä¢¾eè²Ü`–çôi€ê@;š!ÀþP+眜¯9“~á?Œ¦SÒnŽ¡»¹ÂÅ9@meMlÍQê‰õ%éÒ)$¥ÕYÖIáFåmÃé¬Ö­0è²§kU×ñ@¯Gª%j¹À§Gi‰©@jD¢IÂh ¼é¬Ò"`I¯æ!ÌãýÁ½‚ +êN×Ùõ§ê®ÕýÕ6}­³ýL¤äòº¥Î7¬¨ó¨³"4_Ý}9 ““°’Ì®…?ŸðÚxòùÃåTE`ì&Ó4³H`ÿÇMÅ6Ss ޜɜ­Ö\p:p¾æJº ö\ <ŸøðÜýÀüú¨íúÀDZÍ=Æn ö“©xik“TÕ¨†Ír´3žÎ7±~l=|áè`€#–£˜£’ŠW>¯Ô®¤øÌ÷éPÆ ¼_sýp:p¾¢Í÷ÒnŽÁÐdRøä§€È%Ñb|€Ãðe–‹ì©!C¨Â£ƒÂçw;6oÑjb nTy5.iµM/xÒÕ,¿;@æ‘/Ó²„€Ø«1N@/µõd@©@•³w% ºAÜQ¼¡¹k°X`hg°š° ´I\ºà[Æ?ƒÿà?Ü›3™3ûëå‰6ŸVlt_²ÃÚx0âæê€¥Í/ǨÞRÙµò xKˆ¯«À5‘û÷[€Ëó5W«ÈšœtØÿ`ÀeÂu‹û-(ùªém@C¥Ï˜¾kÛ6p•·5C€„±þÑNT=°&5-nŒÞ6ütÛÉMá÷Ý®ˆJW§…ìz±HõL’0¸qïòÖKŠ ¡ù.ÚÍ1ˆ‹¯/ÎZ¾ ð†ònæ» ¬¼;ÛÆBØNVÅ,—úÖsÒ¸h]lð‘jÛ X„…–=³,Ç,á ô»¯ç7˜˜c¾$Èv °ÈeMźw”c1êS y 8*礳£ ¦ðŸV›ç¹Âf¥0åýì'sø}Bë÷sÆŽÿ<¶?Pp&¯"×p¾u~॑T]³¶_ß~‹é4¹¸î»¥Õ3 'ïŒÌ&w*ÚüÖæýQ`VoCCƒu@凊å1@ε,›O^Ôd¡õ¸f§;ð®¡%T=\N:µðä#`^¤í&; €×o)Ÿ;e7ÿÒfGȲ-vYSa ¸í’ÛY@ÍÑÐü/8œ6zDß"äœï¿^Ý‚‚._^¿þך|Ûœ¹|ÀKàÝÞ¼!%ªÍOX®ˆOŸæßÁR>ÞýHõ=‘qïž“»­¢ùUÐ'š6t˜íãMn™÷˜90yáLú{44l…î1ÐÐдv ?KG@+ i~':Œc`)òö 9`Ã>@_¯…‰ÀE¹KO9kŒkÇŽ[^[vXŠJ–’‘v4¿Æ1¼|þxñÃ@ÀWùœäéýÀîMn•§ž×jŸÍye p:p½æJ¶ZÚÕ/Óýïù|kÍ«a©(üÚõwŒkþ-ºú- Íï@‡q â!R¥_ˆE1*ëÙ^.µx›¨ºwwý/<®œu.\Þr¯ÕnÍ,‰3kMkÍÄdÙaÒ¹(‹€CÞ¶^bÀÈ˽O* Pk¬LÚ=¾°:o$8ÚØ®³2g¹*¥„Ô$s[ìéÒ,8 øàìýJpÄru¯jŸÖîþzisÌú4ekm„oÍ9Î3­¶J+½_|¬XœZÂZaž2ÊUÿJÇë)ÑüÞtÇ YÛ·o¿EÀ!ý³+/Ø%9E>…=›×<,5Lnìkx_õ˜ì@Åó|xâ™+H¼ÑÜpžˆÅßMÑÌfYÔÎî lþd;ÀfVÛü*¹ÊÊÒuó=vg‡?ɘ%¸ˆi³xx;Xïæ(Jâ8×ÛÜ‹l6BÄÀP4TVWù ñÙvZÿÔ% üfhù³…À­aQûþN{÷Ä¢£ßŸ¥ÉÉ”¾{ÎE£ "òõç}“gfƒ•F6r'¬Û»*‹Ýw‰æO¡Ã8†8×w‚‘/€¦ÛM“š>ƒd†ø¡}RffæOL\x8™zàÊÞ3@ᙼŠpEàË󀺆ښ]G,Ç¢’Óд'Æ1˜1fE[I!i|©iÀ ½}ò»ne‡ŠM‹yùT¥'JzÀÁѧïz*]}„׊$ÖX¥½&ȬIßûq10þf?;m KŸ°zÿöGW€Ì¿±g¦µÊ¢ À¥w'sŽæÉÙ³; p™pÙ}Ïäâ웄e+€äñ×ãÆ³/…޶{w‘ë²°ö—Ýæ©€à¡yB¯â›lël'«x–KcŸiëõî ˆ¾s76šï}€¾ÐüYt˜µ4 z­ÄŸM‡™c ¡¡é8ÐŽ††¦ ´c ¡¡iíhhhÚÐæ­„™Ùœ9‡³Û,š€*èOÓý±ü›uê’zò8%tEXtdate:create2013-02-01T15:44:40-06:00×·VI%tEXtdate:modify2013-02-01T15:44:40-06:00¦êîõ>tEXtsvg:comment Created with Inkscape (http://www.inkscape.org/) þEG³IEND®B`‚keystone-2014.1/doc/source/images/authComp.svg0000664000175400017540000001512712323716267022432 0ustar jenkinsjenkins00000000000000 image/svg+xml Auth Component OpenStack Service Reject unauthenticated requests Forward authenticated requests keystone-2014.1/doc/source/extensions/0000775000175400017540000000000012323716511021045 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/source/extensions/federation-configuration.rst0000664000175400017540000000317312323716267026600 0ustar jenkinsjenkins00000000000000.. Copyright 2014 OpenStack, Foundation All Rights Reserved. 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. ============================== Enabling Federation Extension ============================== To enable the federation extension: 1. Add the federation extension driver to the ``[federation]`` section in ``keystone.conf``. For example:: [federation] driver = keystone.contrib.federation.backends.sql.Federation 2. Add the ``saml2`` authentication method to the ``[auth]`` section in ``keystone.conf``:: [auth] methods = external,password,token,saml2 saml2 = keystone.auth.plugins.saml2.Saml2 3. Add the ``federation_extension`` middleware to the ``api_v3`` pipeline in ``keystone-paste.ini``. For example:: [pipeline:api_v3] pipeline = access_log sizelimit url_normalize token_auth admin_token_auth xml_body json_body ec2_extension s3_extension federation_extension service_v3 4. Create the federation extension tables if using the provided SQL backend. For example:: ./bin/keystone-manage db_sync --extension federation keystone-2014.1/doc/source/extensions/revoke-configuration.rst0000664000175400017540000000311112323716267025743 0ustar jenkinsjenkins00000000000000 .. 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. ================================ Enabling the OS-REVOKE Extension ================================ .. WARNING:: The ``OS-REVOKE`` Extension is considered experimental in Icehouse and will continue to see improvement over the next development cycle. To enable the ``OS-REVOKE`` extension: 1. Add the driver fields and values in the ``[revoke]`` section in ``keystone.conf``. For the KVS Driver:: [revoke] driver = keystone.contrib.revoke.backends.kvs.Revoke For the SQL driver:: driver = keystone.contrib.revoke.backends.sql.Revoke 2. Add the required ``filter`` to the ``pipeline`` in ``keystone-paste.ini``:: [filter:revoke_extension] paste.filter_factory = keystone.contrib.revoke.routers:RevokeExtension.factory [pipeline:api_v3] pipeline = access_log sizelimit url_normalize token_auth admin_token_auth xml_body json_body revoke_extension service_v3 3. Create the extension tables if using the provided SQL backend:: ./bin/keystone-manage db_sync --extension revoke keystone-2014.1/doc/source/extensions/endpoint_filter-configuration.rst0000664000175400017540000000330312323716267027640 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2013 OpenStack, Foundation All Rights Reserved. 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. ================================== Enabling Endpoint Filter Extension ================================== To enable the endpoint filter extension: 1. add the endpoint filter extension catalog driver to the ``[catalog]`` section in ``keystone.conf``. example:: [catalog] driver = keystone.contrib.endpoint_filter.backends.catalog_sql.EndpointFilterCatalog 2. add the ``endpoint_filter_extension`` filter to the ``api_v3`` pipeline in ``keystone-paste.ini``. example:: [pipeline:api_v3] pipeline = access_log sizelimit url_normalize token_auth admin_token_auth xml_body json_body ec2_extension s3_extension endpoint_filter_extension service_v3 3. create the endpoint filter extension tables if using the provided sql backend. example:: ./bin/keystone-manage db_sync --extension endpoint_filter 4. optional: change ``return_all_endpoints_if_no_filter`` the ``[endpoint_filter]`` section in ``keystone.conf`` to return an empty catalog if no associations are made. example:: [endpoint_filter] return_all_endpoints_if_no_filter = False keystone-2014.1/doc/source/extensions/oauth1-configuration.rst0000664000175400017540000000306012323716267025654 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2013 OpenStack, Foundation All Rights Reserved. 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. ============================= Enabling the OAuth1 Extension ============================= To enable the OAuth1 extension: 1. Optionally, add the oauth1 extension driver to the ``[oauth1]`` section in ``keystone.conf``. For example:: [oauth1] driver = keystone.contrib.oauth1.backends.sql.OAuth1 2. Add the ``oauth1`` authentication method to the ``[auth]`` section in ``keystone.conf``:: [auth] methods = external,password,token,oauth1 oauth1 = keystone.auth.plugins.oauth1.OAuth 3. Add the ``oauth1_extension`` filter to the ``api_v3`` pipeline in ``keystone-paste.ini``. For example:: [pipeline:api_v3] pipeline = access_log sizelimit url_normalize token_auth admin_token_auth xml_body json_body ec2_extension s3_extension oauth1_extension service_v3 4. Create the OAuth1 extension tables if using the provided SQL backend. For example:: ./bin/keystone-manage db_sync --extension oauth1 keystone-2014.1/doc/source/configuringservices.rst0000664000175400017540000002052212323716272023463 0ustar jenkinsjenkins00000000000000.. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ========================================== Configuring Services to work with Keystone ========================================== .. toctree:: :maxdepth: 1 Once Keystone is installed and running (see :doc:`configuration`), services need to be configured to work with it. To do this, we primarily install and configure middleware for the OpenStack service to handle authentication tasks or otherwise interact with Keystone. In general: * Clients making calls to the service will pass in an authentication token. * The Keystone middleware will look for and validate that token, taking the appropriate action. * It will also retrive additional information from the token such as user name, id, tenant name, id, roles, etc... The middleware will pass those data down to the service as headers. More details on the architecture of that setup is described in :doc:`middlewarearchitecture` Setting up credentials ====================== Admin Token ----------- For a default installation of Keystone, before you can use the REST API, you need to define an authorization token. This is configured in ``keystone.conf`` file under the section ``[DEFAULT]``. In the sample file provided with the keystone project, the line defining this token is:: [DEFAULT] admin_token = ADMIN A "shared secret" that can be used to bootstrap Keystone. This token does not represent a user, and carries no explicit authorization. To disable in production (highly recommended), remove AdminTokenAuthMiddleware from your paste application pipelines (for example, in keystone-paste.ini) Setting up tenants, users, and roles ------------------------------------ You need to minimally define a tenant, user, and role to link the tenant and user as the most basic set of details to get other services authenticating and authorizing with keystone. You will also want to create service users for nova, glance, swift, etc. to be able to use to authenticate users against keystone. The ``auth_token`` middleware supports using either the shared secret described above as `admin_token` or users for each service. See :doc:`configuration` for a walk through on how to create tenants, users, and roles. Setting up services =================== Creating Service Users ---------------------- To configure the OpenStack services with service users, we need to create a tenant for all the services, and then users for each of the services. We then assign those service users an Admin role on the service tenant. This allows them to validate tokens - and authenticate and authorize other user requests. Create a tenant for the services, typically named 'service' (however, the name can be whatever you choose):: keystone tenant-create --name=service This returns a UUID of the tenant - keep that, you'll need it when creating the users and specifying the roles. Create service users for nova, glance, swift, and neutron (or whatever subset is relevant to your deployment):: keystone user-create --name=nova \ --pass=Sekr3tPass \ --tenant_id=[the uuid of the tenant] \ --email=nova@nothing.com Repeat this for each service you want to enable. Email is a required field in keystone right now, but not used in relation to the service accounts. Each of these commands will also return a UUID of the user. Keep those to assign the Admin role. For adding the Admin role to the service accounts, you'll need to know the UUID of the role you want to add. If you don't have them handy, you can look it up quickly with:: keystone role-list Once you have it, assign the service users to the Admin role. This is all assuming that you've already created the basic roles and settings as described in :doc:`configuration`: keystone user-role-add --tenant_id=[uuid of the service tenant] \ --user=[uuid of the service account] \ --role=[uuid of the Admin role] Defining Services ----------------- Keystone also acts as a service catalog to let other OpenStack systems know where relevant API endpoints exist for OpenStack Services. The OpenStack Dashboard, in particular, uses this heavily - and this **must** be configured for the OpenStack Dashboard to properly function. The endpoints for these services are defined in a template, an example of which is in the project as the file ``etc/default_catalog.templates``. Keystone supports two means of defining the services, one is the catalog template, as described above - in which case everything is detailed in that template. The other is a SQL backend for the catalog service, in which case after keystone is online, you need to add the services to the catalog:: keystone service-create --name=nova \ --type=compute \ --description="Nova Compute Service" keystone service-create --name=ec2 \ --type=ec2 \ --description="EC2 Compatibility Layer" keystone service-create --name=glance \ --type=image \ --description="Glance Image Service" keystone service-create --name=keystone \ --type=identity \ --description="Keystone Identity Service" keystone service-create --name=swift \ --type=object-store \ --description="Swift Service" Setting Up Middleware ===================== Keystone Auth-Token Middleware -------------------------------- The Keystone auth_token middleware is a WSGI component that can be inserted in the WSGI pipeline to handle authenticating tokens with Keystone. You can get more details of the middleware in :doc:`middlewarearchitecture`. Configuring Nova to use Keystone -------------------------------- When configuring Nova, it is important to create a admin service token for the service (from the Configuration step above) and include that as the key 'admin_token' in Nova's api-paste.ini [filter:authtoken] section or in nova.conf [keystone_authtoken] section. Configuring Swift to use Keystone --------------------------------- Similar to Nova, swift can be configured to use Keystone for authentication rather than its built in 'tempauth'. Refer to the `overview_auth` documentation in Swift. Auth-Token Middleware with Username and Password ------------------------------------------------ It is also possible to configure Keystone's auth_token middleware using the 'admin_user' and 'admin_password' options. When using the 'admin_user' and 'admin_password' options the 'admin_token' parameter is optional. If 'admin_token' is specified it will by used only if the specified token is still valid. Here is an example paste config filter that makes use of the 'admin_user' and 'admin_password' parameters:: [filter:authtoken] paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory auth_port = 35357 auth_host = 127.0.0.1 auth_token = 012345SECRET99TOKEN012345 admin_user = admin admin_password = keystone123 It should be noted that when using this option an admin tenant/role relationship is required. The admin user is granted access to to the 'Admin' role to the 'admin' tenant. The auth_token middleware can also be configured in nova.conf [keystone_authtoken] section to keep paste config clean of site-specific parameters:: [filter:authtoken] paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory and in nova.conf:: [DEFAULT] ... auth_strategy=keystone [keystone_authtoken] auth_port = 35357 auth_host = 127.0.0.1 admin_user = admin admin_password = keystone123 keystone-2014.1/doc/source/man/0000775000175400017540000000000012323716511017421 5ustar jenkinsjenkins00000000000000keystone-2014.1/doc/source/man/keystone-all.rst0000664000175400017540000001155712323716267022603 0ustar jenkinsjenkins00000000000000============ keystone-all ============ ------------------------ Keystone Startup Command ------------------------ :Author: openstack@lists.openstack.org :Date: 2014-02-14 :Copyright: OpenStack Foundation :Version: 2014.1 :Manual section: 1 :Manual group: cloud computing SYNOPSIS ======== :: keystone-all [-h] [--config-dir DIR] [--config-file PATH] [--debug] [--log-config-append PATH] [--log-date-format DATE_FORMAT] [--log-dir LOG_DIR] [--log-file PATH] [--log-format FORMAT] [--nodebug] [--nostandard-threads] [--nouse-syslog] [--nouse-syslog-rfc-format] [--noverbose] [--pydev-debug-host PYDEV_DEBUG_HOST] [--pydev-debug-port PYDEV_DEBUG_PORT] [--standard-threads] [--syslog-log-facility SYSLOG_LOG_FACILITY] [--use-syslog] [--use-syslog-rfc-format] [--verbose] [--version] DESCRIPTION =========== keystone-all starts both the service and administrative APIs in a single process to provide catalog, authorization, and authentication services for OpenStack. OPTIONS ======= -h, --help show this help message and exit --config-dir DIR Path to a config directory to pull \*.conf files from. This file set is sorted, so as to provide a predictable parse order if individual options are over-ridden. The set is parsed after the file(s) specified via previous --config-file, arguments hence over-ridden options in the directory take precedence. --config-file PATH Path to a config file to use. Multiple config files can be specified, with values in later files taking precedence. The default files used are: None --debug, -d Print debugging output (set logging level to DEBUG instead of default WARNING level). --log-config-append PATH, --log_config PATH The name of logging configuration file. It does not disable existing loggers, but just appends specified logging configuration to any other existing logging options. Please see the Python logging module documentation for details on logging configuration files. --log-date-format DATE_FORMAT Format string for %(asctime)s in log records. Default: None --log-dir LOG_DIR, --logdir LOG_DIR (Optional) The base directory used for relative --log- file paths --log-file PATH, --logfile PATH (Optional) Name of log file to output to. If no default is set, logging will go to stdout. --log-format FORMAT DEPRECATED. A logging.Formatter log message format string which may use any of the available logging.LogRecord attributes. This option is deprecated. Please use logging_context_format_string and logging_default_format_string instead. --nodebug The inverse of --debug --nostandard-threads The inverse of --standard-threads --nouse-syslog The inverse of --use-syslog --nouse-syslog-rfc-format The inverse of --use-syslog-rfc-format --noverbose The inverse of --verbose --pydev-debug-host PYDEV_DEBUG_HOST Host to connect to for remote debugger. --pydev-debug-port PYDEV_DEBUG_PORT Port to connect to for remote debugger. --standard-threads Do not monkey-patch threading system modules. --syslog-log-facility SYSLOG_LOG_FACILITY Syslog facility to receive log lines --use-syslog Use syslog for logging. Existing syslog format is DEPRECATED during I, and then will be changed in J to honor RFC5424 --use-syslog-rfc-format (Optional) Use syslog rfc5424 format for logging. If enabled, will add APP-NAME (RFC5424) before the MSG part of the syslog message. The old format without APP-NAME is deprecated in I, and will be removed in J. --verbose, -v Print more verbose output (set logging level to INFO instead of default WARNING level). --version show program's version number and exit FILES ===== None SEE ALSO ======== * `OpenStack Keystone `__ SOURCE ====== * Keystone source is managed in GitHub `Keystone `__ * Keystone bugs are managed at Launchpad `Keystone `__ keystone-2014.1/doc/source/man/keystone-manage.rst0000664000175400017540000001165412323716267023261 0ustar jenkinsjenkins00000000000000=============== keystone-manage =============== --------------------------- Keystone Management Utility --------------------------- :Author: openstack@lists.openstack.org :Date: 2014-02-14 :Copyright: OpenStack Foundation :Version: 2014.1 :Manual section: 1 :Manual group: cloud computing SYNOPSIS ======== keystone-manage [options] DESCRIPTION =========== ``keystone-manage`` is the command line tool which interacts with the Keystone service to initialize and update data within Keystone. Generally, ``keystone-manage`` is only used for operations that cannot be accomplished with the HTTP API, such data import/export and database migrations. USAGE ===== ``keystone-manage [options] action [additional args]`` General keystone-manage options: -------------------------------- * ``--help`` : display verbose help output. Invoking ``keystone-manage`` by itself will give you some usage information. Available commands: * ``db_sync``: Sync the database. * ``db_version``: Print the current migration version of the database. * ``pki_setup``: Initialize the certificates used to sign tokens. * ``ssl_setup``: Generate certificates for SSL. * ``token_flush``: Purge expired tokens. OPTIONS ======= -h, --help show this help message and exit --config-dir DIR Path to a config directory to pull \*.conf files from. This file set is sorted, so as to provide a predictable parse order if individual options are over-ridden. The set is parsed after the file(s) specified via previous --config-file, arguments hence over-ridden options in the directory take precedence. --config-file PATH Path to a config file to use. Multiple config files can be specified, with values in later files taking precedence. The default files used are: None --debug, -d Print debugging output (set logging level to DEBUG instead of default WARNING level). --log-config-append PATH, --log_config PATH The name of logging configuration file. It does not disable existing loggers, but just appends specified logging configuration to any other existing logging options. Please see the Python logging module documentation for details on logging configuration files. --log-date-format DATE_FORMAT Format string for %(asctime)s in log records. Default: None --log-dir LOG_DIR, --logdir LOG_DIR (Optional) The base directory used for relative --log- file paths --log-file PATH, --logfile PATH (Optional) Name of log file to output to. If no default is set, logging will go to stdout. --log-format FORMAT DEPRECATED. A logging.Formatter log message format string which may use any of the available logging.LogRecord attributes. This option is deprecated. Please use logging_context_format_string and logging_default_format_string instead. --nodebug The inverse of --debug --nostandard-threads The inverse of --standard-threads --nouse-syslog The inverse of --use-syslog --nouse-syslog-rfc-format The inverse of --use-syslog-rfc-format --noverbose The inverse of --verbose --pydev-debug-host PYDEV_DEBUG_HOST Host to connect to for remote debugger. --pydev-debug-port PYDEV_DEBUG_PORT Port to connect to for remote debugger. --standard-threads Do not monkey-patch threading system modules. --syslog-log-facility SYSLOG_LOG_FACILITY Syslog facility to receive log lines --use-syslog Use syslog for logging. Existing syslog format is DEPRECATED during I, and then will be changed in J to honor RFC5424 --use-syslog-rfc-format (Optional) Use syslog rfc5424 format for logging. If enabled, will add APP-NAME (RFC5424) before the MSG part of the syslog message. The old format without APP-NAME is deprecated in I, and will be removed in J. --verbose, -v Print more verbose output (set logging level to INFO instead of default WARNING level). --version show program's version number and exit FILES ===== None SEE ALSO ======== * `OpenStack Keystone `__ SOURCE ====== * Keystone is sourced in GitHub `Keystone `__ * Keystone bugs are managed at Launchpad `Keystone `__ keystone-2014.1/doc/source/apache-httpd.rst0000664000175400017540000000700612323716267021755 0ustar jenkinsjenkins00000000000000 .. Copyright 2011-2012 OpenStack Foundation All Rights Reserved. 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. ========================= Running Keystone in HTTPD ========================= SSL === To run Keystone in HTTPD, first enable SSL support. This is optional, but highly recommended. Install mod_nss according to your distribution, then apply the following patch and restart HTTPD:: --- /etc/httpd/conf.d/nss.conf.orig 2012-03-29 12:59:06.319470425 -0400 +++ /etc/httpd/conf.d/nss.conf 2012-03-29 12:19:38.862721465 -0400 @@ -17,7 +17,7 @@ # Note: Configurations that use IPv6 but not IPv4-mapped addresses need two # Listen directives: "Listen [::]:8443" and "Listen 0.0.0.0:443" # -Listen 8443 +Listen 443 ## ## SSL Global Context @@ -81,7 +81,7 @@ ## SSL Virtual Host Context ## - + # General setup for the virtual host #DocumentRoot "/etc/httpd/htdocs" Firewall -------- Add the following rule to IPTables in order to ensure the SSL traffic can pass your firewall:: -A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT it goes right before:: -A INPUT -j REJECT --reject-with icmp-host-prohibited Files ----- Copy the file httpd/wsgi-keystone.conf to the appropriate location for your apache server, most likely:: /etc/httpd/conf.d/wsgi-keystone.conf Create the directory ``/var/www/cgi-bin/keystone/``. You can either hardlink or softlink the files ``main`` and ``admin`` to the file ``keystone.py`` in this directory. For a distribution appropriate place, it should probably be copied to:: /usr/share/openstack/keystone/httpd/keystone.py Keystone's primary configuration file (``etc/keystone.conf``) and the PasteDeploy configuration file (``etc/keystone-paste.ini``) must be readable to HTTPD in one of the default locations described in :doc:`configuration`. SELinux ------- If you are running with SELinux enabled (and you should be) make sure that the file has the appropriate SELinux context to access the linked file. If you have the file in /var/www/cgi-bin, you can do this by running:: sudo restorecon /var/www/cgi-bin Putting it somewhere else requires you set up your SELinux policy accordingly. Keystone Configuration ---------------------- Make sure you use either the ``SQL`` or the ``memcached`` driver for ``tokens``, otherwise the tokens will not be shared between the processes of the Apache HTTPD server. For ``SQL,`` in ``/etc/keystone/keystone.conf`` make sure you have set:: [token] driver = keystone.token.backends.sql.Token For ``memcache,`` in ``/etc/keystone/keystone.conf`` make sure you have set:: [token] driver = keystone.token.backends.memcache.Token In both cases, all servers that are storing tokens need a shared backend. This means either that both point to the same database server, or both point to a common memcached instance. keystone-2014.1/doc/source/extension_development.rst0000664000175400017540000002414012323716267024027 0ustar jenkinsjenkins00000000000000.. 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. ===================================== Keystone Extensions Development Guide ===================================== General ======= This Extension Development Guide provides some mocked code to use as an Extension code base in the ``keystone/contrib/example`` folder. - All Extensions must be created in the ``keystone/contrib`` folder. - The new Extension code must be contained in a new folder under ``contrib``. - Whenever possible an Extension should follow the following directory structure convention:: keystone/contrib/ └── my_extension    ├── backends (optional)    │   ├── __init__.py (mandatory)    │   └── sql.py (optional)    │   └── kvs.py (optional)    ├── migrate_repo (optional)    │   ├── __init__.py (mandatory)    │   ├── migrate.cfg (mandatory)    │   └── versions (mandatory) │      ├── 001_create_tables.py (mandatory) │      └── __init__.py (mandatory)    ├── __init__.py (mandatory)    ├── core.py (mandatory)    ├── controllers.py (mandatory for API Extension)    └── routers.py (mandatory for API Extension) - If the Extension implements an API Extension the ``controllers.py`` and ``routers.py`` must be present and correctly handle the API Extension requests and responses. - If the Extension implements backends a ``backends`` folder should exist. Backends are defined to store data persistently and can use a variety of technologies. Please see the Backends section in this document for more info. - If the Extension adds data structures, then a ``migrate_repo`` folder should exist. - If configuration changes are required/introduced in the ``keystone.conf.sample`` file, these should be kept disabled as default and have their own section. - If configuration changes are required/introduced in the ``keystone-paste.ini``, the new filter must be declared. - The module may register to listen to events by declaring the corresponding callbacks in the ``core.py`` file. - The new extension should be disabled by default (it should not affect the default application pipelines). Modifying the `keystone.conf.sample` File ========================================= In the case an Extension needs to change the ``keystone.conf.sample`` file, it must follow the config file conventions and introduce a dedicated section. Example:: [example] driver = keystone.contrib.example.backends.sql.mySQLClass [my_other_extension] extension_flag = False The Extension parameters expressed should be commented out since, by default, extensions are disabled. Example:: [example] #driver = keystone.contrib.example.backends.sql.mySQLClass [my_other_extension] #extension_flag = False In case the Extension is overriding or re-implementing an existing portion of Keystone, the required change should be commented in the ``configuration.rst`` but not placed in the `keystone.conf.sample` file to avoid unnecessary confusion. Modifying the ``keystone-paste.ini`` File ========================================= In the case an Extension is augmenting a pipeline introducing a new ``filter`` and/or APIs in the ``OS`` namespace, a corresponding ``filter:`` section is necessary to be introduced in the ``keystone-paste.ini`` file. The Extension should declare the filter factory constructor in the ``ini`` file. Example:: [filter:example] paste.filter_factory = keystone.contrib.example.routers:ExampleRouter. factory The ``filter`` must not be placed in the ``pipeline`` and treated as optional. How to add the extension in the pipeline should be specified in detail in the ``configuration.rst`` file. Package Constructor File ======================== The ``__init__.py`` file represents the package constructor. Extension needs to import what is necessary from the ``core.py`` module. Example: .. code:: python from keystone.contrib.example.core import * Core ==== The ``core.py`` file represents the main module defining the data structure and interface. In the ``Model View Control`` (MVC) model it represents the ``Model`` part and it delegates to the ``Backends`` the data layer implementation. In case the ``core.py`` file contains a ``Manager`` and a ``Driver`` it must provide the dependency injections for the ``Controllers`` and/or other modules using the ``Manager``. A good practice is to call the dependency ``extension_name_api``. Example: .. code:: python @dependency.provider('example_api') class Manager(manager.Manager): Routers ======= ``routers.py`` have the objective of routing the HTTP requests and direct them to the correct method within the ``Controllers``. Extension routers are extending the ``wsgi.ExtensionRouter``. Example: .. code:: python from keystone.common import wsgi from keystone.contrib.example import controllers class ExampleRouter(wsgi.ExtensionRouter): PATH_PREFIX = '/OS-EXAMPLE' def add_routes(self, mapper): example_controller = controllers.ExampleV3Controller() mapper.connect(self.PATH_PREFIX + '/example', controller=example_controller, action='do_something', conditions=dict(method=['GET'])) Controllers =========== ``controllers.py`` have the objective of handing requests and implement the Extension logic. Controllers are consumers of 'Managers' API and must have all the dependency injections required. ``Controllers`` are extending the ``V3Controller`` class. Example: .. code:: python @dependency.requires('identity_api', 'example_api') class ExampleV3Controller(controller.V3Controller): pass Backends ======== The ``backends`` folder provides the model implementations for the different backends supported by the Extension. See General above for an example directory structure. If a SQL backend is provided, in the ``sql.py`` backend implementation it is mandatory to define the new table(s) that the Extension introduces and the attributes they are composed of. For more information on backends, refer to the `Keystone Architecture `_ documentation. Example: .. code:: python class ExampleSQLBackend(sql.ModelBase, sql.DictBase): """example table description.""" __tablename__ = 'example_table' attributes = ['id', 'type', 'extra'] example_id = sql.Column(sql.String(64), primary_key=True, nullable=False) ... SQL Migration Repository ======================== In case the Extension is adding SQL data structures, these must be stored in separate tables and must not be included in the ``migrate_repo`` of the core Keystone. Please refer to the ``migrate.cfg`` file to configure the Extension repository. In order to create the Extension tables and their attributes, a ``db_sync`` command must be executed. Example:: ./bin/keystone-manage db_sync --extension example Event Callbacks --------------- Extensions may provide callbacks to Keystone (Identity) events. Extensions must provide the list of events of interest and the corresponding callbacks. Events are issued upon successful creation, modification, and deletion of the following Keystone resources: - ``group`` - ``project`` - ``role`` - ``user`` The extension's ``Manager`` class must contain the ``event_callbacks`` attribute. It is a dictionary listing as keys those events that are of interest and the values should be the respective callbacks. Event callback registration is done via the dependency injection mechanism. During dependency provider registration, the ``dependency.provider`` decorator looks for the ``event_callbacks`` class attribute. If it exists the event callbacks are registered accordingly. In order to enable event callbacks, the extension's ``Manager`` class must also be a dependency provider. Example: .. code:: python # Since this is a dependency provider. Any code module using this or any # other dependency provider (uses the dependency.provider decorator) # will be enabled for the attribute based notification @dependency.provider('example_api') class ExampleManager(manager.Manager): """Example Manager. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): self.event_callbacks = { # Here we add the the event_callbacks class attribute that # calls project_deleted_callback when a project is deleted. 'deleted': { 'project': [ self.project_deleted_callback]}} super(ExampleManager, self).__init__( 'keystone.contrib.example.core.ExampleDriver') def project_deleted_callback(self, context, message): # cleanup data related to the deleted project here A callback must accept the following parameters: - ``service`` - the service information (e.g. identity) - ``resource_type`` - the resource type (e.g. project) - ``operation`` - the operation (updated, created, deleted) - ``payload`` - the actual payload info of the resource that was acted on Current callback operations: - ``created`` - ``deleted`` - ``updated`` Example: .. code:: python def project_deleted_callback(self, service, resource_type, operation, payload): keystone-2014.1/doc/source/installing.rst0000664000175400017540000000771712323716267021570 0ustar jenkinsjenkins00000000000000.. Copyright 2012 OpenStack Foundation Copyright 2012 Nebula, Inc All Rights Reserved. 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. =================== Installing Keystone =================== This document describes how to install Keystone in order to use it. If you are intending to develop on or with Keystone, please read :doc:`developing` and :doc:`setup`. Installing from Source ---------------------- The source install instructions specifically avoid using platform specific packages, instead using the source for the code and the Python Package Index (PyPi_). .. _PyPi: http://pypi.python.org/pypi It's expected that your system already has python_, pip_, and git_ available. .. _python: http://www.python.org .. _pip: http://www.pip-installer.org/en/latest/installing.html .. _git: http://git-scm.com/ Clone the keystone repository:: git clone http://github.com/openstack/keystone.git cd keystone Install the dependencies to run keystone:: sudo pip install -r requirements.txt And at this point, you should have all the pieces you need to run keystone installed on your system. The following commands should be available on the commandline path: * ``keystone`` the keystone client, used to configure keystone * ``keystone-manage`` used to bootstrap keystone data * ``keystone-all`` used to run the keystone services You will find sample configuration files in ``etc/`` * keystone.conf * keystone-paste.ini * logging.conf * policy.json * default_catalog.templates From here, refer to :doc:`configuration` to choose which backend drivers to enable and use. Once configured, you should be able to run keystone by issuing the command:: keystone-all which (by default) will show logging on the console from which it was started. Once started, you can initialize data in keystone for use with the rest of openstack, as described in :doc:`configuringservices`. An excellent reference implementation of setting up keystone is DEVSTACK_, most commonly used for development and testing setup of not only Keystone, but all of the core OpenStack projects. .. _DEVSTACK: http://devstack.org/ The script with the latest examples of intializing data in Keystone is a bash script called keystone_data.sh_ .. _keystone_data.sh: https://github.com/openstack-dev/devstack/blob/master/files/keystone_data.sh Installing from packages: Ubuntu -------------------------------- Ubuntu is providing packages for Keystone for Precise. To install keystone on Ubuntu:: sudo apt-get install keystone In using Ubuntu's packages, the packages will set up a user account for the Keystone service (`keystone`), and place default configurations in ``/etc/keystone``. The debian installer will also ask you about configuration options for setting up and running Keystone. As of this writing, the defaults for Keystone backends are all SQL based, stored locally in a sqlite. Once installed, you still need to initialize data in Keystone, which you can find described in :doc:`configuringservices`. Installing from packages: Fedora -------------------------------- Installing Keystone with Fedora 17 is documented at http://fedoraproject.org/wiki/Getting_started_with_OpenStack_on_Fedora_17. To install the packages:: sudo yum install --enablerepo=updates-testing openstack-keystone Once installed, you can configure keystone based on the instructions at: http://fedoraproject.org/wiki/Getting_started_with_OpenStack_on_Fedora_17#Configuring_Keystone_for_authentication keystone-2014.1/doc/source/event_notifications.rst0000664000175400017540000000574512323716267023475 0ustar jenkinsjenkins00000000000000 .. Copyright 2013 IBM Corp. 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. ============================ Keystone Event Notifications ============================ Keystone provides notifications about usage data so that 3rd party applications can use the data for billing, monitoring, or quota purposes. This document describes the current inclusions and exclusions for Keystone usage notifications. Notifications for Create/Update/Delete Events ============================================= A notification is sent when a resource is successfully ``created``, ``updated``, or ``deleted``. The following resource types (where a ```` is always a singular noun) produce notifications. For resource types that are immutable, like trusts, notifications are only sent on creation and deletion of that resource. Resource types that should be immutable from a Keystone perspective will not support update operations: - ``group`` - ``project`` (i.e. "tenant") - ``role`` - ``user`` - ``trust`` (immutable resource - no ``updated`` notification) The following message template is used to form a message when an operation on a resource completes successfully:: { "event_type": "identity..", "message_id": "", "payload": { "resource_info": "" }, "priority": "INFO", "publisher_id": "identity.", "timestamp": "" } Notifications for create, update and delete events are all similar to each other, where either ``created``, ``updated`` or ``deleted`` is inserted as the ```` in the above notification's ``event_type``. The ``priority`` of the notification being sent is not configurable through the Keystone configuration file. This value is defaulted to INFO for all notifications sent in Keystone's case. If the operation fails, the notification won't be sent, and no special error notification will be sent. Information about the error is handled through normal exception paths. Notification Example ^^^^^^^^^^^^^^^^^^^^ This is an example of a notification sent for a newly created user:: { "event_type": "identity.user.created", "message_id": "0156ee79-b35f-4cef-ac37-d4a85f231c69", "payload": { "resource_info": "671da331c47d4e29bb6ea1d270154ec3" }, "priority": "INFO", "publisher_id": "identity.host1234", "timestamp": "2013-08-29 19:03:45.960280" } keystone-2014.1/doc/source/external-auth.rst0000664000175400017540000001503712323716267022177 0ustar jenkinsjenkins00000000000000=========================================== Using external authentication with Keystone =========================================== .. _external-auth: When Keystone is executed in a web server like :doc:`Apache HTTPD ` it is possible to use external authentication methods different from the authentication provided by the identity store backend or the different authentication plugins. For example, this makes possible to use an SQL identity backend together with, X.509 authentication or Kerberos, for example, instead of using the username and password combination. When a web server is in charge of authentication, it is normally possible to set the ``REMOTE_USER`` environment variable so that it can be used in the underlying application. Keystone can be configured to use that environment variable if set, so that the authentication is handled by the web server. Configuration ============= In Identity API v2, there is no way to disable external authentication. In order to activate the external authentication mechanism for Identity API v3, the ``external`` method must be in the list of enabled authentication methods. By default it is enabled, so if you don't want to use external authentication, remove it from the ``methods`` option in the ``auth`` section. To configure the plugin that should be used set the ``external`` option again in the ``auth`` section. There are two external authentication method plugins provided by Keystone: * ``keystone.auth.plugins.external.Default``: This plugin won't take into account the domain information that the external authentication method may pass down to Keystone and will always use the configured default domain. The ``REMOTE_USER`` variable is the username. * ``keystone.auth.plugins.external.Domain``: This plugin expects that the ``REMOTE_DOMAIN`` variable contains the domain for the user. If this variable is not present, the configured default domain will be used. The ``REMOTE_USER`` variable is the username. Using HTTPD authentication ========================== Web servers like Apache HTTP support many methods of authentication. Keystone can profit from this feature and let the authentication be done in the web server, that will pass down the authenticated user to Keystone using the ``REMOTE_USER`` environment variable. This user must exist in advance in the identity backend so as to get a token from the controller. To use this method, Keystone should be running on :doc:`HTTPD `. X.509 example ------------- The following snippet for the Apache conf will authenticate the user based on a valid X.509 certificate from a known CA:: SSLEngine on SSLCertificateFile /etc/ssl/certs/ssl.cert SSLCertificateKeyFile /etc/ssl/private/ssl.key SSLCACertificatePath /etc/ssl/allowed_cas SSLCARevocationPath /etc/ssl/allowed_cas SSLUserName SSL_CLIENT_S_DN_CN SSLVerifyClient require SSLVerifyDepth 10 (...) Developing a WSGI middleware for authentication =============================================== In addition to the method described above, it is possible to implement other custom authentication mechanisms using the ``REMOTE_USER`` WSGI environment variable. .. ATTENTION:: Please note that even if it is possible to develop a custom authentication module, it is preferable to use the modules in the HTTPD server. Such authentication modules in webservers like Apache have normally undergone years of development and use in production systems and are actively maintained upstream. Developing a custom authentication module that implements the same authentication as an existing Apache module likely introduces a higher security risk. If you find you must implement a custom authentication mechanism, you will need to develop a custom WSGI middleware pipeline component. This middleware should set the environment variable ``REMOTE_USER`` to the authenticated username. Keystone then will assume that the user has been already authenticated upstream and will not try to authenticate it. However, as with HTTPD authentication, the user must exist in advance in the identity backend so that a proper token can be issued. Your code should set the ``REMOTE_USER`` if the user is properly authenticated, following the semantics below: .. code:: python from keystone.common import wsgi class MyMiddlewareAuth(wsgi.Middleware): def __init__(self, *args, **kwargs): super(MyMiddlewareAuth, self).__init__(*args, **kwargs) def process_request(self, request): if request.environ.get('REMOTE_USER', None) is not None: # Assume that it is authenticated upstream return self.application if not self.is_auth_applicable(request): # Not applicable return self.application username = self.do_auth(request): if username is not None: # User is authenticated request.environ['REMOTE_USER'] = username else: # User is not authenticated, render exception raise exception.Unauthorized("Invalid user") Pipeline configuration ---------------------- Once you have your WSGI middleware component developed you have to add it to your pipeline. The first step is to add the middleware to your configuration file. Assuming that your middleware module is ``keystone.middleware.MyMiddlewareAuth``, you can configure it in your ``keystone-paste.ini`` as:: [filter:my_auth] paste.filter_factory = keystone.middleware.MyMiddlewareAuth.factory The second step is to add your middleware to the pipeline. The exact place where you should place it will depend on your code (i.e. if you need for example that the request body is converted from JSON before perform the authentication you should place it after the ``json_body`` filter) but it should be set before the ``public_service`` (for the ``public_api`` pipeline) or ``admin_service`` (for the ``admin_api`` pipeline), since they consume authentication. For example, if the original pipeline looks like this:: [pipeline:public_api] pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body debug ec2_extension user_crud_extension public_service Your modified pipeline might then look like this:: [pipeline:public_api] pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body my_auth debug ec2_extension user_crud_extension public_service keystone-2014.1/keystone/0000775000175400017540000000000012323716511016442 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/auth/0000775000175400017540000000000012323716511017403 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/auth/plugins/0000775000175400017540000000000012323716511021064 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/auth/plugins/oauth1.py0000664000175400017540000000535012323716267022652 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone import auth from keystone.common import controller from keystone.common import dependency from keystone.contrib.oauth1 import core as oauth from keystone.contrib.oauth1 import validator from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils LOG = log.getLogger(__name__) @dependency.optional('oauth_api') class OAuth(auth.AuthMethodHandler): method = 'oauth1' def authenticate(self, context, auth_info, auth_context): """Turn a signed request with an access key into a keystone token.""" if not self.oauth_api: raise exception.Unauthorized(_('%s not supported') % self.method) headers = context['headers'] oauth_headers = oauth.get_oauth_headers(headers) access_token_id = oauth_headers.get('oauth_token') if not access_token_id: raise exception.ValidationError( attribute='oauth_token', target='request') acc_token = self.oauth_api.get_access_token(access_token_id) expires_at = acc_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Access token is expired')) url = controller.V3Controller.base_url(context, context['path']) access_verifier = oauth.ResourceEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth.token_generator) result, request = access_verifier.validate_protected_resource_request( url, http_method='POST', body=context['query_string'], headers=headers, realms=None ) if not result: msg = _('Could not validate the access token') raise exception.Unauthorized(msg) auth_context['user_id'] = acc_token['authorizing_user_id'] auth_context['access_token_id'] = access_token_id auth_context['project_id'] = acc_token['project_id'] keystone-2014.1/keystone/auth/plugins/password.py0000664000175400017540000001145212323716267023313 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone import auth from keystone.common import dependency from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log METHOD_NAME = 'password' LOG = log.getLogger(__name__) @dependency.requires('assignment_api', 'identity_api') class UserAuthInfo(object): @staticmethod def create(auth_payload): user_auth_info = UserAuthInfo() user_auth_info._validate_and_normalize_auth_data(auth_payload) return user_auth_info def __init__(self): self.user_id = None self.password = None self.user_ref = None def _assert_domain_is_enabled(self, domain_ref): if not domain_ref.get('enabled'): msg = _('Domain is disabled: %s') % (domain_ref['id']) LOG.warning(msg) raise exception.Unauthorized(msg) def _assert_user_is_enabled(self, user_ref): if not user_ref.get('enabled', True): msg = _('User is disabled: %s') % (user_ref['id']) LOG.warning(msg) raise exception.Unauthorized(msg) def _lookup_domain(self, domain_info): domain_id = domain_info.get('id') domain_name = domain_info.get('name') domain_ref = None if not domain_id and not domain_name: raise exception.ValidationError(attribute='id or name', target='domain') try: if domain_name: domain_ref = self.assignment_api.get_domain_by_name( domain_name) else: domain_ref = self.assignment_api.get_domain(domain_id) except exception.DomainNotFound as e: LOG.exception(e) raise exception.Unauthorized(e) self._assert_domain_is_enabled(domain_ref) return domain_ref def _validate_and_normalize_auth_data(self, auth_payload): if 'user' not in auth_payload: raise exception.ValidationError(attribute='user', target=METHOD_NAME) user_info = auth_payload['user'] user_id = user_info.get('id') user_name = user_info.get('name') user_ref = None if not user_id and not user_name: raise exception.ValidationError(attribute='id or name', target='user') self.password = user_info.get('password') try: if user_name: if 'domain' not in user_info: raise exception.ValidationError(attribute='domain', target='user') domain_ref = self._lookup_domain(user_info['domain']) user_ref = self.identity_api.get_user_by_name( user_name, domain_ref['id']) else: user_ref = self.identity_api.get_user(user_id) domain_ref = self.assignment_api.get_domain( user_ref['domain_id']) self._assert_domain_is_enabled(domain_ref) except exception.UserNotFound as e: LOG.exception(e) raise exception.Unauthorized(e) self._assert_user_is_enabled(user_ref) self.user_ref = user_ref self.user_id = user_ref['id'] self.domain_id = domain_ref['id'] @dependency.requires('identity_api') class Password(auth.AuthMethodHandler): method = METHOD_NAME def authenticate(self, context, auth_payload, user_context): """Try to authenticate against the identity backend.""" user_info = UserAuthInfo.create(auth_payload) # FIXME(gyee): identity.authenticate() can use some refactoring since # all we care is password matches try: self.identity_api.authenticate( context, user_id=user_info.user_id, password=user_info.password, domain_scope=user_info.domain_id) except AssertionError: # authentication failed because of invalid username or password msg = _('Invalid username or password') raise exception.Unauthorized(msg) if 'user_id' not in user_context: user_context['user_id'] = user_info.user_id keystone-2014.1/keystone/auth/plugins/token.py0000664000175400017540000000603712323716272022570 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone import auth from keystone.common import wsgi from keystone import exception from keystone.openstack.common import log from keystone.openstack.common import timeutils from keystone.token import provider LOG = log.getLogger(__name__) class Token(auth.AuthMethodHandler): method = 'token' def __init__(self): self.provider = provider.Manager() def authenticate(self, context, auth_payload, user_context): try: if 'id' not in auth_payload: raise exception.ValidationError(attribute='id', target=self.method) token_id = auth_payload['id'] response = self.provider.validate_token(token_id) #for V3 tokens, the essential data is under the 'token' value. #For V2, the comparable data was nested under 'access' token_ref = response.get('token', response.get('access')) #Do not allow tokens used for delegation to #create another token, or perform any changes of #state in Keystone. TO do so is to invite elevation of #privilege attacks if 'OS-TRUST:trust' in token_ref: raise exception.Forbidden() if 'trust' in token_ref: raise exception.Forbidden() if 'trust_id' in token_ref.get('metadata', {}): raise exception.Forbidden() if 'OS-OAUTH1' in token_ref: raise exception.Forbidden() wsgi.validate_token_bind(context, token_ref) #new tokens are not allowed to extend the expiration #time of an old token, otherwise, they could be extened #forever. The expiration value was stored at different #locations in v2 and v3 tokens. expires_at = token_ref.get('expires_at') if not expires_at: expires_at = token_ref.get('expires') if not expires_at: expires_at = timeutils.normalize_time( timeutils.parse_isotime(token_ref['token']['expires'])) user_context.setdefault('expires_at', expires_at) user_context.setdefault('user_id', token_ref['user']['id']) user_context['extras'].update(token_ref.get('extras', {})) user_context['method_names'].extend(token_ref.get('methods', [])) except AssertionError as e: LOG.error(e) raise exception.Unauthorized(e) keystone-2014.1/keystone/auth/plugins/saml2.py0000664000175400017540000001040212323716272022455 0ustar jenkinsjenkins00000000000000# 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 six.moves.urllib import parse from keystone import auth from keystone.common import dependency from keystone import config from keystone.contrib import federation from keystone.contrib.federation import utils from keystone import exception from keystone.openstack.common import jsonutils from keystone.openstack.common import log from keystone.openstack.common import timeutils CONF = config.CONF LOG = log.getLogger(__name__) @dependency.requires('federation_api', 'identity_api', 'token_api') class Saml2(auth.AuthMethodHandler): method = 'saml2' def authenticate(self, context, auth_payload, auth_context): """Authenticate federated user and return an authentication context. :param context: keystone's request context :param auth_payload: the content of the authentication for a given method :param auth_context: user authentication context, a dictionary shared by all plugins. In addition to ``user_id`` in ``auth_context``, the ``saml2`` plugin sets ``group_ids``. When handling unscoped tokens, ``OS-FEDERATION:identity_provider`` and ``OS-FEDERATION:protocol`` are set as well. """ if 'id' in auth_payload: fields = self._handle_scoped_token(auth_payload) else: fields = self._handle_unscoped_token(context, auth_payload) auth_context.update(fields) def _handle_scoped_token(self, auth_payload): token_ref = self.token_api.get_token(auth_payload['id']) self._validate_expiration(token_ref) _federation = token_ref['user'][federation.FEDERATION] identity_provider = _federation['identity_provider']['id'] protocol = _federation['protocol']['id'] group_ids = [group['id'] for group in _federation['groups']] mapping = self.federation_api.get_mapping_from_idp_and_protocol( identity_provider, protocol) self._validate_groups(group_ids, mapping['id']) return { 'user_id': token_ref['user_id'], 'group_ids': group_ids } def _handle_unscoped_token(self, context, auth_payload): assertion = dict(self._get_assertion_params_from_env(context)) identity_provider = auth_payload['identity_provider'] protocol = auth_payload['protocol'] mapping = self.federation_api.get_mapping_from_idp_and_protocol( identity_provider, protocol) rules = jsonutils.loads(mapping['rules']) rule_processor = utils.RuleProcessor(rules) mapped_properties = rule_processor.process(assertion) self._validate_groups(mapped_properties['group_ids'], mapping['id']) return { 'user_id': parse.quote(mapped_properties['name']), 'group_ids': mapped_properties['group_ids'], federation.IDENTITY_PROVIDER: identity_provider, federation.PROTOCOL: protocol } def _validate_expiration(self, token_ref): if timeutils.utcnow() > token_ref['expires']: raise exception.Unauthorized(_('Federation token is expired')) def _validate_groups(self, group_ids, mapping_id): if not group_ids: raise exception.MissingGroups(mapping_id=mapping_id) for group_id in group_ids: try: self.identity_api.get_group(group_id) except exception.GroupNotFound: raise exception.MappedGroupNotFound( group_id=group_id, mapping_id=mapping_id) def _get_assertion_params_from_env(self, context): prefix = CONF.federation.assertion_prefix for k, v in context['environment'].items(): if k.startswith(prefix): yield (k, v) keystone-2014.1/keystone/auth/plugins/__init__.py0000664000175400017540000000000012323716267023173 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/auth/plugins/external.py0000664000175400017540000001363012323716267023273 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Keystone External Authentication Plugins""" import abc import six from keystone import auth from keystone.common import config from keystone.common import dependency from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import versionutils CONF = config.CONF @six.add_metaclass(abc.ABCMeta) class Base(auth.AuthMethodHandler): method = 'external' def authenticate(self, context, auth_info, auth_context): """Use REMOTE_USER to look up the user in the identity backend. auth_context is an in-out variable that will be updated with the user_id from the actual user from the REMOTE_USER env variable. """ try: REMOTE_USER = context['environment']['REMOTE_USER'] except KeyError: msg = _('No authenticated user') raise exception.Unauthorized(msg) try: user_ref = self._authenticate(REMOTE_USER, context) auth_context['user_id'] = user_ref['id'] if ('kerberos' in CONF.token.bind and (context['environment'].get('AUTH_TYPE', '').lower() == 'negotiate')): auth_context['bind']['kerberos'] = user_ref['name'] except Exception: msg = _('Unable to lookup user %s') % (REMOTE_USER) raise exception.Unauthorized(msg) @abc.abstractmethod def _authenticate(self, remote_user, context): """Look up the user in the identity backend. Return user_ref """ pass @dependency.requires('identity_api') class DefaultDomain(Base): def _authenticate(self, remote_user, context): """Use remote_user to look up the user in the identity backend.""" domain_id = CONF.identity.default_domain_id user_ref = self.identity_api.get_user_by_name(remote_user, domain_id) return user_ref @dependency.requires('assignment_api', 'identity_api') class Domain(Base): def _authenticate(self, remote_user, context): """Use remote_user to look up the user in the identity backend. The domain will be extracted from the REMOTE_DOMAIN environment variable if present. If not, the default domain will be used. """ username = remote_user try: domain_name = context['environment']['REMOTE_DOMAIN'] except KeyError: domain_id = CONF.identity.default_domain_id else: domain_ref = self.assignment_api.get_domain_by_name(domain_name) domain_id = domain_ref['id'] user_ref = self.identity_api.get_user_by_name(username, domain_id) return user_ref class ExternalDefault(DefaultDomain): """Deprecated. Please use keystone.auth.external.DefaultDomain instead.""" @versionutils.deprecated( as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='keystone.auth.external.DefaultDomain', remove_in=+1) def __init__(self): super(ExternalDefault, self).__init__() class ExternalDomain(Domain): """Deprecated. Please use keystone.auth.external.Domain instead.""" @versionutils.deprecated( as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='keystone.auth.external.Domain', remove_in=+1) def __init__(self): super(ExternalDomain, self).__init__() @dependency.requires('identity_api') class LegacyDefaultDomain(Base): """Deprecated. Please use keystone.auth.external.DefaultDomain instead. This plugin exists to provide compatibility for the unintended behavior described here: https://bugs.launchpad.net/keystone/+bug/1253484 """ @versionutils.deprecated( as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='keystone.auth.external.DefaultDomain', remove_in=+1) def __init__(self): super(LegacyDefaultDomain, self).__init__() def _authenticate(self, remote_user, context): """Use remote_user to look up the user in the identity backend.""" # NOTE(dolph): this unintentionally discards half the REMOTE_USER value names = remote_user.split('@') username = names.pop(0) domain_id = CONF.identity.default_domain_id user_ref = self.identity_api.get_user_by_name(username, domain_id) return user_ref @dependency.requires('assignment_api', 'identity_api') class LegacyDomain(Base): """Deprecated. Please use keystone.auth.external.Domain instead.""" @versionutils.deprecated( as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='keystone.auth.external.Domain', remove_in=+1) def __init__(self): super(LegacyDomain, self).__init__() def _authenticate(self, remote_user, context): """Use remote_user to look up the user in the identity backend. If remote_user contains an `@` assume that the substring before the rightmost `@` is the username, and the substring after the @ is the domain name. """ names = remote_user.rsplit('@', 1) username = names.pop(0) if names: domain_name = names[0] domain_ref = self.assignment_api.get_domain_by_name(domain_name) domain_id = domain_ref['id'] else: domain_id = CONF.identity.default_domain_id user_ref = self.identity_api.get_user_by_name(username, domain_id) return user_ref keystone-2014.1/keystone/auth/controllers.py0000664000175400017540000004760712323716272022345 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json from keystoneclient.common import cms import six from keystone.common import controller from keystone.common import dependency from keystone.common import wsgi from keystone import config from keystone.contrib import federation from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone.openstack.common import log from keystone.openstack.common import timeutils LOG = log.getLogger(__name__) CONF = config.CONF # registry of authentication methods AUTH_METHODS = {} AUTH_PLUGINS_LOADED = False def load_auth_methods(): global AUTH_PLUGINS_LOADED if AUTH_PLUGINS_LOADED: # Only try and load methods a single time. return # config.setup_authentication should be idempotent, call it to ensure we # have setup all the appropriate configuration options we may need. config.setup_authentication() for plugin in CONF.auth.methods: if '.' in plugin: # NOTE(morganfainberg): if '.' is in the plugin name, it should be # imported rather than used as a plugin identifier. plugin_class = plugin driver = importutils.import_object(plugin) if not hasattr(driver, 'method'): raise ValueError(_('Cannot load an auth-plugin by class-name ' 'without a "method" attribute defined: %s'), plugin_class) else: plugin_class = CONF.auth.get(plugin) driver = importutils.import_object(plugin_class) if hasattr(driver, 'method'): if driver.method != plugin: raise ValueError(_('Driver requested method %(req)s does ' 'not match plugin name %(plugin)s.') % {'req': driver.method, 'plugin': plugin}) else: LOG.warning(_('Auth Plugin %s does not have a "method" ' 'attribute.'), plugin) setattr(driver, 'method', plugin) if driver.method in AUTH_METHODS: raise ValueError(_('Auth plugin %(plugin)s is requesting ' 'previously registered method %(method)s') % {'plugin': plugin_class, 'method': driver.method}) AUTH_METHODS[driver.method] = driver AUTH_PLUGINS_LOADED = True def get_auth_method(method_name): global AUTH_METHODS if method_name not in AUTH_METHODS: raise exception.AuthMethodNotSupported() return AUTH_METHODS[method_name] # TODO(blk-u): this class doesn't use identity_api directly, but makes it # available for consumers. Consumers should probably not be getting # identity_api from this since it's available in global registry, then # identity_api should be removed from this list. @dependency.requires('assignment_api', 'identity_api', 'trust_api') class AuthInfo(object): """Encapsulation of "auth" request.""" @staticmethod def create(context, auth=None): auth_info = AuthInfo(context, auth=auth) auth_info._validate_and_normalize_auth_data() return auth_info def __init__(self, context, auth=None): self.context = context self.auth = auth self._scope_data = (None, None, None) # self._scope_data is (domain_id, project_id, trust_ref) # project scope: (None, project_id, None) # domain scope: (domain_id, None, None) # trust scope: (None, None, trust_ref) # unscoped: (None, None, None) def _assert_project_is_enabled(self, project_ref): # ensure the project is enabled if not project_ref.get('enabled', True): msg = _('Project is disabled: %s') % project_ref['id'] LOG.warning(msg) raise exception.Unauthorized(msg) def _assert_domain_is_enabled(self, domain_ref): if not domain_ref.get('enabled'): msg = _('Domain is disabled: %s') % (domain_ref['id']) LOG.warning(msg) raise exception.Unauthorized(msg) def _lookup_domain(self, domain_info): domain_id = domain_info.get('id') domain_name = domain_info.get('name') domain_ref = None if not domain_id and not domain_name: raise exception.ValidationError(attribute='id or name', target='domain') try: if domain_name: domain_ref = self.assignment_api.get_domain_by_name( domain_name) else: domain_ref = self.assignment_api.get_domain(domain_id) except exception.DomainNotFound as e: LOG.exception(e) raise exception.Unauthorized(e) self._assert_domain_is_enabled(domain_ref) return domain_ref def _lookup_project(self, project_info): project_id = project_info.get('id') project_name = project_info.get('name') project_ref = None if not project_id and not project_name: raise exception.ValidationError(attribute='id or name', target='project') try: if project_name: if 'domain' not in project_info: raise exception.ValidationError(attribute='domain', target='project') domain_ref = self._lookup_domain(project_info['domain']) project_ref = self.assignment_api.get_project_by_name( project_name, domain_ref['id']) else: project_ref = self.assignment_api.get_project(project_id) except exception.ProjectNotFound as e: LOG.exception(e) raise exception.Unauthorized(e) self._assert_project_is_enabled(project_ref) return project_ref def _lookup_trust(self, trust_info): trust_id = trust_info.get('id') if not trust_id: raise exception.ValidationError(attribute='trust_id', target='trust') trust = self.trust_api.get_trust(trust_id) if not trust: raise exception.TrustNotFound(trust_id=trust_id) return trust def _validate_and_normalize_scope_data(self): """Validate and normalize scope data.""" if 'scope' not in self.auth: return if sum(['project' in self.auth['scope'], 'domain' in self.auth['scope'], 'OS-TRUST:trust' in self.auth['scope']]) != 1: raise exception.ValidationError( attribute='project, domain, or OS-TRUST:trust', target='scope') if 'project' in self.auth['scope']: project_ref = self._lookup_project(self.auth['scope']['project']) self._scope_data = (None, project_ref['id'], None) elif 'domain' in self.auth['scope']: domain_ref = self._lookup_domain(self.auth['scope']['domain']) self._scope_data = (domain_ref['id'], None, None) elif 'OS-TRUST:trust' in self.auth['scope']: if not CONF.trust.enabled: raise exception.Forbidden('Trusts are disabled.') trust_ref = self._lookup_trust( self.auth['scope']['OS-TRUST:trust']) # TODO(ayoung): when trusts support domains, fill in domain data if 'project_id' in trust_ref: project_ref = self._lookup_project( {'id': trust_ref['project_id']}) self._scope_data = (None, project_ref['id'], trust_ref) else: self._scope_data = (None, None, trust_ref) def _validate_auth_methods(self): if 'identity' not in self.auth: raise exception.ValidationError(attribute='identity', target='auth') # make sure auth methods are provided if 'methods' not in self.auth['identity']: raise exception.ValidationError(attribute='methods', target='identity') # make sure all the method data/payload are provided for method_name in self.get_method_names(): if method_name not in self.auth['identity']: raise exception.ValidationError(attribute=method_name, target='identity') # make sure auth method is supported for method_name in self.get_method_names(): if method_name not in AUTH_METHODS: raise exception.AuthMethodNotSupported() def _validate_and_normalize_auth_data(self): """Make sure "auth" is valid.""" # make sure "auth" exist if not self.auth: raise exception.ValidationError(attribute='auth', target='request body') self._validate_auth_methods() self._validate_and_normalize_scope_data() def get_method_names(self): """Returns the identity method names. :returns: list of auth method names """ # Sanitizes methods received in request's body # Filters out duplicates, while keeping elements' order. method_names = [] for method in self.auth['identity']['methods']: if method not in method_names: method_names.append(method) return method_names def get_method_data(self, method): """Get the auth method payload. :returns: auth method payload """ if method not in self.auth['identity']['methods']: raise exception.ValidationError(attribute=method, target='identity') return self.auth['identity'][method] def get_scope(self): """Get scope information. Verify and return the scoping information. :returns: (domain_id, project_id, trust_ref). If scope to a project, (None, project_id, None) will be returned. If scoped to a domain, (domain_id, None, None) will be returned. If scoped to a trust, (None, project_id, trust_ref), Will be returned, where the project_id comes from the trust definition. If unscoped, (None, None, None) will be returned. """ return self._scope_data def set_scope(self, domain_id=None, project_id=None, trust=None): """Set scope information.""" if domain_id and project_id: msg = _('Scoping to both domain and project is not allowed') raise ValueError(msg) if domain_id and trust: msg = _('Scoping to both domain and trust is not allowed') raise ValueError(msg) if project_id and trust: msg = _('Scoping to both project and trust is not allowed') raise ValueError(msg) self._scope_data = (domain_id, project_id, trust) @dependency.requires('assignment_api', 'identity_api', 'token_api', 'token_provider_api', 'trust_api') class Auth(controller.V3Controller): # Note(atiwari): From V3 auth controller code we are # calling protection() wrappers, so we need to setup # the member_name and collection_name attributes of # auth controller code. # In the absence of these attributes, default 'entity' # string will be used to represent the target which is # generic. Policy can be defined using 'entity' but it # would not reflect the exact entity that is in context. # We are defining collection_name = 'tokens' and # member_name = 'token' to facilitate policy decisions. collection_name = 'tokens' member_name = 'token' def __init__(self, *args, **kw): super(Auth, self).__init__(*args, **kw) config.setup_authentication() def authenticate_for_token(self, context, auth=None): """Authenticate user and issue a token.""" include_catalog = 'nocatalog' not in context['query_string'] try: auth_info = AuthInfo.create(context, auth=auth) auth_context = {'extras': {}, 'method_names': [], 'bind': {}} self.authenticate(context, auth_info, auth_context) if auth_context.get('access_token_id'): auth_info.set_scope(None, auth_context['project_id'], None) self._check_and_set_default_scoping(auth_info, auth_context) (domain_id, project_id, trust) = auth_info.get_scope() if trust: self.trust_api.consume_use(trust['id']) method_names = auth_info.get_method_names() method_names += auth_context.get('method_names', []) # make sure the list is unique method_names = list(set(method_names)) expires_at = auth_context.get('expires_at') # NOTE(morganfainberg): define this here so it is clear what the # argument is during the issue_v3_token provider call. metadata_ref = None (token_id, token_data) = self.token_provider_api.issue_v3_token( auth_context['user_id'], method_names, expires_at, project_id, domain_id, auth_context, trust, metadata_ref, include_catalog) return render_token_data_response(token_id, token_data, created=True) except exception.TrustNotFound as e: raise exception.Unauthorized(e) def _check_and_set_default_scoping(self, auth_info, auth_context): (domain_id, project_id, trust) = auth_info.get_scope() if trust: project_id = trust['project_id'] if domain_id or project_id or trust: # scope is specified return # Skip scoping when unscoped federated token is being issued if federation.IDENTITY_PROVIDER in auth_context: return # fill in default_project_id if it is available try: user_ref = self.identity_api.get_user(auth_context['user_id']) except exception.UserNotFound as e: LOG.exception(e) raise exception.Unauthorized(e) default_project_id = user_ref.get('default_project_id') if not default_project_id: # User has no default project. He shall get an unscoped token. return # make sure user's default project is legit before scoping to it try: default_project_ref = self.assignment_api.get_project( default_project_id) default_project_domain_ref = self.assignment_api.get_domain( default_project_ref['domain_id']) if (default_project_ref.get('enabled', True) and default_project_domain_ref.get('enabled', True)): if self.assignment_api.get_roles_for_user_and_project( user_ref['id'], default_project_id): auth_info.set_scope(project_id=default_project_id) else: msg = _("User %(user_id)s doesn't have access to" " default project %(project_id)s. The token will" " be unscoped rather than scoped to the project.") LOG.warning(msg, {'user_id': user_ref['id'], 'project_id': default_project_id}) else: msg = _("User %(user_id)s's default project %(project_id)s is" " disabled. The token will be unscoped rather than" " scoped to the project.") LOG.warning(msg, {'user_id': user_ref['id'], 'project_id': default_project_id}) except (exception.ProjectNotFound, exception.DomainNotFound): # default project or default project domain doesn't exist, # will issue unscoped token instead msg = _("User %(user_id)s's default project %(project_id)s not" " found. The token will be unscoped rather than" " scoped to the project.") LOG.warning(msg, {'user_id': user_ref['id'], 'project_id': default_project_id}) def authenticate(self, context, auth_info, auth_context): """Authenticate user.""" # user has been authenticated externally if 'REMOTE_USER' in context['environment']: external = get_auth_method('external') external.authenticate(context, auth_info, auth_context) # need to aggregate the results in case two or more methods # are specified auth_response = {'methods': []} for method_name in auth_info.get_method_names(): method = get_auth_method(method_name) resp = method.authenticate(context, auth_info.get_method_data(method_name), auth_context) if resp: auth_response['methods'].append(method_name) auth_response[method_name] = resp if auth_response["methods"]: # authentication continuation required raise exception.AdditionalAuthRequired(auth_response) if 'user_id' not in auth_context: msg = _('User not found') raise exception.Unauthorized(msg) @controller.protected() def check_token(self, context): token_id = context.get('subject_token_id') self.token_provider_api.check_v3_token(token_id) @controller.protected() def revoke_token(self, context): token_id = context.get('subject_token_id') return self.token_provider_api.revoke_token(token_id) @controller.protected() def validate_token(self, context): token_id = context.get('subject_token_id') include_catalog = 'nocatalog' not in context['query_string'] token_data = self.token_provider_api.validate_v3_token( token_id) if not include_catalog and 'catalog' in token_data['token']: del token_data['token']['catalog'] return render_token_data_response(token_id, token_data) @controller.protected() def revocation_list(self, context, auth=None): if not CONF.token.revoke_by_id: raise exception.Gone() tokens = self.token_api.list_revoked_tokens() for t in tokens: expires = t['expires'] if not (expires and isinstance(expires, six.text_type)): t['expires'] = timeutils.isotime(expires) data = {'revoked': tokens} json_data = json.dumps(data) signed_text = cms.cms_sign_text(json_data, CONF.signing.certfile, CONF.signing.keyfile) return {'signed': signed_text} #FIXME(gyee): not sure if it belongs here or keystone.common. Park it here # for now. def render_token_data_response(token_id, token_data, created=False): """Render token data HTTP response. Stash token ID into the X-Subject-Token header. """ headers = [('X-Subject-Token', token_id)] if created: status = (201, 'Created') else: status = (200, 'OK') return wsgi.render_response(body=token_data, status=status, headers=headers) keystone-2014.1/keystone/auth/core.py0000664000175400017540000000677012323716267020727 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import abc import six from keystone import exception @six.add_metaclass(abc.ABCMeta) class AuthMethodHandler(object): """Abstract base class for an authentication plugin.""" def __init__(self): pass @abc.abstractmethod def authenticate(self, context, auth_payload, auth_context): """Authenticate user and return an authentication context. :param context: keystone's request context :auth_payload: the content of the authentication for a given method :auth_context: user authentication context, a dictionary shared by all plugins. It contains "method_names" and "extras" by default. "method_names" is a list and "extras" is a dictionary. If successful, plugin must set ``user_id`` in ``auth_context``. ``method_name`` is used to convey any additional authentication methods in case authentication is for re-scoping. For example, if the authentication is for re-scoping, plugin must append the previous method names into ``method_names``. Also, plugin may add any additional information into ``extras``. Anything in ``extras`` will be conveyed in the token's ``extras`` attribute. Here's an example of ``auth_context`` on successful authentication:: { "extras": {}, "methods": [ "password", "token" ], "user_id": "abc123" } Plugins are invoked in the order in which they are specified in the ``methods`` attribute of the ``identity`` object. For example, ``custom-plugin`` is invoked before ``password``, which is invoked before ``token`` in the following authentication request:: { "auth": { "identity": { "custom-plugin": { "custom-data": "sdfdfsfsfsdfsf" }, "methods": [ "custom-plugin", "password", "token" ], "password": { "user": { "id": "s23sfad1", "password": "secrete" } }, "token": { "id": "sdfafasdfsfasfasdfds" } } } } :returns: None if authentication is successful. Authentication payload in the form of a dictionary for the next authentication step if this is a multi step authentication. :raises: exception.Unauthorized for authentication failure """ raise exception.Unauthorized() keystone-2014.1/keystone/auth/routers.py0000664000175400017540000000312612323716267021472 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.auth import controllers def append_v3_routers(mapper, routers): auth_controller = controllers.Auth() mapper.connect('/auth/tokens', controller=auth_controller, action='authenticate_for_token', conditions=dict(method=['POST'])) mapper.connect('/auth/tokens', controller=auth_controller, action='check_token', conditions=dict(method=['HEAD'])) mapper.connect('/auth/tokens', controller=auth_controller, action='revoke_token', conditions=dict(method=['DELETE'])) mapper.connect('/auth/tokens', controller=auth_controller, action='validate_token', conditions=dict(method=['GET'])) mapper.connect('/auth/tokens/OS-PKI/revoked', controller=auth_controller, action='revocation_list', conditions=dict(method=['GET'])) keystone-2014.1/keystone/auth/__init__.py0000664000175400017540000000130312323716272021515 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2013 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. from keystone.auth import controllers from keystone.auth.core import * from keystone.auth import routers keystone-2014.1/keystone/cli.py0000664000175400017540000001321212323716267017572 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from __future__ import absolute_import import os from oslo.config import cfg import pbr.version from keystone.common import openssl from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.common import utils from keystone import config from keystone import token CONF = config.CONF class BaseApp(object): name = None @classmethod def add_argument_parser(cls, subparsers): parser = subparsers.add_parser(cls.name, help=cls.__doc__) parser.set_defaults(cmd_class=cls) return parser class DbSync(BaseApp): """Sync the database.""" name = 'db_sync' @classmethod def add_argument_parser(cls, subparsers): parser = super(DbSync, cls).add_argument_parser(subparsers) parser.add_argument('version', default=None, nargs='?', help=('Migrate the database up to a specified ' 'version. If not provided, db_sync will ' 'migrate the database to the latest known ' 'version.')) parser.add_argument('--extension', default=None, help=('Migrate the database for the specified ' 'extension. If not provided, db_sync will ' 'migrate the common repository.')) return parser @staticmethod def main(): version = CONF.command.version extension = CONF.command.extension migration_helpers.sync_database_to_version(extension, version) class DbVersion(BaseApp): """Print the current migration version of the database.""" name = 'db_version' @classmethod def add_argument_parser(cls, subparsers): parser = super(DbVersion, cls).add_argument_parser(subparsers) parser.add_argument('--extension', default=None, help=('Migrate the database for the specified ' 'extension. If not provided, db_sync will ' 'migrate the common repository.')) @staticmethod def main(): extension = CONF.command.extension migration_helpers.print_db_version(extension) class BaseCertificateSetup(BaseApp): """Common user/group setup for PKI and SSL generation.""" @classmethod def add_argument_parser(cls, subparsers): parser = super(BaseCertificateSetup, cls).add_argument_parser(subparsers) running_as_root = (os.geteuid() == 0) parser.add_argument('--keystone-user', required=running_as_root) parser.add_argument('--keystone-group', required=running_as_root) return parser @staticmethod def get_user_group(): keystone_user_id = None keystone_group_id = None try: a = CONF.command.keystone_user if a: keystone_user_id = utils.get_unix_user(a)[0] except KeyError: raise ValueError("Unknown user '%s' in --keystone-user" % a) try: a = CONF.command.keystone_group if a: keystone_group_id = utils.get_unix_group(a)[0] except KeyError: raise ValueError("Unknown group '%s' in --keystone-group" % a) return keystone_user_id, keystone_group_id class PKISetup(BaseCertificateSetup): """Set up Key pairs and certificates for token signing and verification.""" name = 'pki_setup' @classmethod def main(cls): keystone_user_id, keystone_group_id = cls.get_user_group() conf_pki = openssl.ConfigurePKI(keystone_user_id, keystone_group_id) conf_pki.run() class SSLSetup(BaseCertificateSetup): """Create key pairs and certificates for HTTPS connections.""" name = 'ssl_setup' @classmethod def main(cls): keystone_user_id, keystone_group_id = cls.get_user_group() conf_ssl = openssl.ConfigureSSL(keystone_user_id, keystone_group_id) conf_ssl.run() class TokenFlush(BaseApp): """Flush expired tokens from the backend.""" name = 'token_flush' @classmethod def main(cls): token_manager = token.Manager() token_manager.driver.flush_expired_tokens() CMDS = [ DbSync, DbVersion, PKISetup, SSLSetup, TokenFlush, ] def add_command_parsers(subparsers): for cmd in CMDS: cmd.add_argument_parser(subparsers) command_opt = cfg.SubCommandOpt('command', title='Commands', help='Available commands', handler=add_command_parsers) def main(argv=None, config_files=None): CONF.register_cli_opt(command_opt) config.configure() sql.initialize() config.set_default_for_default_log_levels() CONF(args=argv[1:], project='keystone', version=pbr.version.VersionInfo('keystone').version_string(), usage='%(prog)s [' + '|'.join([cmd.name for cmd in CMDS]) + ']', default_config_files=config_files) config.setup_logging() CONF.command.cmd_class.main() keystone-2014.1/keystone/common/0000775000175400017540000000000012323716511017732 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/serializer.py0000664000175400017540000003141012323716272022460 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """ Dict <--> XML de/serializer. The identity API prefers attributes over elements, so we serialize that way by convention, with a few hardcoded exceptions. """ from lxml import etree import re import six from keystone.openstack.common.gettextutils import _ DOCTYPE = '' XMLNS = 'http://docs.openstack.org/identity/api/v2.0' XMLNS_LIST = [ { 'value': 'http://docs.openstack.org/identity/api/v2.0' }, { 'prefix': 'OS-KSADM', 'value': 'http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0', }, ] PARSER = etree.XMLParser( resolve_entities=False, remove_comments=True, remove_pis=True) # NOTE(dolph): lxml.etree.Entity() is just a callable that currently returns an # lxml.etree._Entity instance, which doesn't appear to be part of the # public API, so we discover the type dynamically to be safe ENTITY_TYPE = type(etree.Entity('x')) def from_xml(xml): """Deserialize XML to a dictionary.""" if xml is None: return None deserializer = XmlDeserializer() return deserializer(xml) def to_xml(d, xmlns=None): """Serialize a dictionary to XML.""" if d is None: return None serialize = XmlSerializer() return serialize(d, xmlns) class XmlDeserializer(object): def __call__(self, xml_str): """Returns a dictionary populated by decoding the given xml string.""" dom = etree.fromstring(xml_str.strip(), PARSER) return self.walk_element(dom, True) def _deserialize_links(self, links): return dict((x.attrib['rel'], x.attrib['href']) for x in links) @staticmethod def _qualified_name(tag, namespace): """Returns a qualified tag name. The tag name may contain the namespace prefix or not, which can be determined by specifying the parameter namespace. """ m = re.search('[^}]+$', tag) tag_name = m.string[m.start():] if not namespace: return tag_name bracket = re.search('[^{]+$', tag) ns = m.string[bracket.start():m.start() - 1] #If the namespace is #http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0 #for the root element, a prefix needs to add in front of the tag name. prefix = None for xmlns in XMLNS_LIST: if xmlns['value'] == ns: prefix = xmlns.get('prefix') break if prefix is not None: return '%(PREFIX)s:%(tag_name)s' \ % {'PREFIX': prefix, 'tag_name': tag_name} else: return tag_name def walk_element(self, element, namespace=False): """Populates a dictionary by walking an etree element.""" values = {} for k, v in six.iteritems(element.attrib): # boolean-looking attributes become booleans in JSON if k in ['enabled', 'truncated']: if v in ['true']: v = True elif v in ['false']: v = False values[self._qualified_name(k, namespace)] = v text = None if element.text is not None: text = element.text.strip() # current spec does not have attributes on an element with text values = values or text or {} decoded_tag = XmlDeserializer._qualified_name(element.tag, namespace) list_item_tag = None if (decoded_tag[-1] == 's' and not values and decoded_tag != 'access'): # FIXME(gyee): special-case lists for now unti we # figure out how to properly handle them. # If any key ends with an 's', we are assuming it is a list. # List element have no attributes. values = list(values) if decoded_tag == 'policies': list_item_tag = 'policy' else: list_item_tag = decoded_tag[:-1] if decoded_tag == 'links': return {'links': self._deserialize_links(element)} links = None truncated = False for child in [self.walk_element(x) for x in element if not isinstance(x, ENTITY_TYPE)]: if list_item_tag: # FIXME(gyee): special-case lists for now until we # figure out how to properly handle them. # If any key ends with an 's', we are assuming it is a list. if list_item_tag in child: values.append(child[list_item_tag]) else: if 'links' in child: links = child['links'] else: truncated = child['truncated'] else: values = dict(values.items() + child.items()) # set empty and none-list element to None to align with JSON if not values: values = "" d = {XmlDeserializer._qualified_name(element.tag, namespace): values} if links: d['links'] = links d['links'].setdefault('next') d['links'].setdefault('previous') if truncated: d['truncated'] = truncated['truncated'] return d class XmlSerializer(object): def __call__(self, d, xmlns=None): """Returns an xml etree populated by the given dictionary. Optionally, namespace the etree by specifying an ``xmlns``. """ links = None truncated = False # FIXME(dolph): skipping links for now for key in d.keys(): if '_links' in key: d.pop(key) # NOTE(gyee, henry-nash): special-case links and truncation # attribute in collections if 'links' == key: if links: # we have multiple links raise Exception('Multiple links found') links = d.pop(key) if 'truncated' == key: if truncated: # we have multiple attributes raise Exception(_('Multiple truncation attributes found')) truncated = d.pop(key) assert len(d.keys()) == 1, ('Cannot encode more than one root ' 'element: %s' % d.keys()) # name the root dom element name = d.keys()[0] m = re.search('[^:]+$', name) root_name = m.string[m.start():] prefix = m.string[0:m.start() - 1] for ns in XMLNS_LIST: if prefix == ns.get('prefix'): xmlns = ns['value'] break # only the root dom element gets an xlmns root = etree.Element(root_name, xmlns=(xmlns or XMLNS)) self.populate_element(root, d[name]) # NOTE(gyee, henry-nash): special-case links and truncation attribute if links: self._populate_links(root, links) if truncated: self._populate_truncated(root, truncated) # TODO(dolph): you can get a doctype from lxml, using ElementTrees return '%s\n%s' % (DOCTYPE, etree.tostring(root, pretty_print=True)) def _populate_links(self, element, links_json): links = etree.Element('links') for k, v in six.iteritems(links_json): if v: link = etree.Element('link') link.set('rel', six.text_type(k)) link.set('href', six.text_type(v)) links.append(link) element.append(links) def _populate_truncated(self, element, truncated_value): truncated = etree.Element('truncated') self._populate_bool(truncated, 'truncated', truncated_value) element.append(truncated) def _populate_list(self, element, k, v): """Populates an element with a key & list value.""" # spec has a lot of inconsistency here! container = element if k == 'media-types': # xsd compliance: contains s # find an existing element or make one container = element.find('media-types') if container is None: container = etree.Element(k) element.append(container) name = k[:-1] elif k == 'serviceCatalog' or k == 'catalog': # xsd compliance: contains s container = etree.Element(k) element.append(container) name = 'service' elif k == 'roles' and element.tag == 'user': name = 'role' elif k == 'endpoints' and element.tag == 'service': name = 'endpoint' elif k == 'values' and element.tag[-1] == 's': # OS convention is to contain lists in a 'values' element, # so the list itself can have attributes, which is # unnecessary in XML name = element.tag[:-1] elif k[-1] == 's': container = etree.Element(k) element.append(container) if k == 'policies': # need to special-case policies since policie is not a word name = 'policy' else: name = k[:-1] else: name = k for item in v: child = etree.Element(name) self.populate_element(child, item) container.append(child) def _populate_dict(self, element, k, v): """Populates an element with a key & dictionary value.""" if k == 'links': # links is a special dict self._populate_links(element, v) else: child = etree.Element(k) self.populate_element(child, v) element.append(child) def _populate_bool(self, element, k, v): """Populates an element with a key & boolean value.""" # booleans are 'true' and 'false' element.set(k, six.text_type(v).lower()) def _populate_str(self, element, k, v): """Populates an element with a key & string value.""" if k in ['description']: # always becomes an element child = etree.Element(k) child.text = six.text_type(v) element.append(child) else: # add attributes to the current element element.set(k, six.text_type(v)) def _populate_number(self, element, k, v): """Populates an element with a key & numeric value.""" # numbers can be handled as strings self._populate_str(element, k, v) def populate_element(self, element, value): """Populates an etree with the given value.""" if isinstance(value, list): self._populate_sequence(element, value) elif isinstance(value, dict): self._populate_tree(element, value) # NOTE(blk-u): For compatibility with Folsom, when serializing the # v2.0 version element also add the links to the base element. if value.get('id') == 'v2.0': for item in value['links']: child = etree.Element('link') self.populate_element(child, item) element.append(child) elif isinstance(value, six.string_types): element.text = six.text_type(value) def _populate_sequence(self, element, l): """Populates an etree with a sequence of elements, given a list.""" # xsd compliance: child elements are singular: has s name = element.tag if element.tag[-1] == 's': name = element.tag[:-1] if name == 'policie': name = 'policy' for item in l: child = etree.Element(name) self.populate_element(child, item) element.append(child) def _populate_tree(self, element, d): """Populates an etree with attributes & elements, given a dict.""" for k, v in six.iteritems(d): if isinstance(v, dict): self._populate_dict(element, k, v) elif isinstance(v, list): self._populate_list(element, k, v) elif isinstance(v, bool): self._populate_bool(element, k, v) elif isinstance(v, six.string_types): self._populate_str(element, k, v) elif type(v) in [int, float, long, complex]: self._populate_number(element, k, v) keystone-2014.1/keystone/common/dependency.py0000664000175400017540000002457412323716272022442 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """This module provides support for dependency injection. Providers are registered via the 'provider' decorator, and dependencies on them are registered with 'requires' or 'optional'. Providers are available to their consumers via an attribute. See the documentation for the individual functions for more detail. See also: https://en.wikipedia.org/wiki/Dependency_injection """ import six from keystone import notifications from keystone.openstack.common.gettextutils import _ # flake8: noqa REGISTRY = {} _future_dependencies = {} _future_optionals = {} _factories = {} class UnresolvableDependencyException(Exception): """An UnresolvableDependencyException is raised when a required dependency is not resolvable; see 'resolve_future_dependencies'. """ def __init__(self, name): msg = 'Unregistered dependency: %s' % name super(UnresolvableDependencyException, self).__init__(msg) def provider(name): """'provider' is a class decorator used to register providers. When 'provider' is used to decorate a class, members of that class will register themselves as providers for the named dependency. As an example, In the code fragment:: @dependency.provider('foo_api') class Foo: def __init__(self): ... ... foo = Foo() The object 'foo' will be registered as a provider for 'foo_api'. No more than one such instance should be created; additional instances will replace the previous ones, possibly resulting in different instances being used by different consumers. """ def wrapper(cls): def wrapped(init): def register_event_callbacks(self): # NOTE(morganfainberg): A provider who has an implicit # dependency on other providers may utilize the event callback # mechanism to react to any changes in those providers. This is # performed at the .provider() mechanism so that we can ensure # that the callback is only ever called once and guaranteed # to be on the properly configured and instantiated backend. if not hasattr(self, 'event_callbacks'): return if not isinstance(self.event_callbacks, dict): msg = _('event_callbacks must be a dict') raise ValueError(msg) for event in self.event_callbacks: if not isinstance(self.event_callbacks[event], dict): msg = _('event_callbacks[%s] must be a dict') % event raise ValueError(msg) for resource_type in self.event_callbacks[event]: # Make sure we register the provider for each event it # cares to call back. callbacks = self.event_callbacks[event][resource_type] if not callbacks: continue if not hasattr(callbacks, '__iter__'): # ensure the callback information is a list # allowing multiple callbacks to exist callbacks = [callbacks] notifications.register_event_callback(event, resource_type, callbacks) def __wrapped_init__(self, *args, **kwargs): """Initialize the wrapped object and add it to the registry.""" init(self, *args, **kwargs) REGISTRY[name] = self register_event_callbacks(self) resolve_future_dependencies(name) return __wrapped_init__ cls.__init__ = wrapped(cls.__init__) _factories[name] = cls return cls return wrapper def _process_dependencies(obj): # Any dependencies that can be resolved immediately are resolved. # Dependencies that cannot be resolved immediately are stored for # resolution in resolve_future_dependencies. def process(obj, attr_name, unresolved_in_out): for dependency in getattr(obj, attr_name, []): if dependency not in REGISTRY: # We don't know about this dependency, so save it for later. unresolved_in_out.setdefault(dependency, []).append(obj) continue setattr(obj, dependency, REGISTRY[dependency]) process(obj, '_dependencies', _future_dependencies) process(obj, '_optionals', _future_optionals) def requires(*dependencies): """'requires' is a class decorator used to inject providers into consumers. The required providers will be made available to instances of the decorated class via an attribute with the same name as the provider. For example, in the code fragment:: @dependency.requires('foo_api', 'bar_api') class FooBarClient: def __init__(self): ... ... client = FooBarClient() The object 'client' will have attributes named 'foo_api' and 'bar_api', which are instances of the named providers. Objects must not rely on the existence of these attributes until after 'resolve_future_dependencies' has been called; they may not exist beforehand. Dependencies registered via 'required' must have providers - if not, an exception will be raised when 'resolve_future_dependencies' is called. """ def wrapper(self, *args, **kwargs): """Inject each dependency from the registry.""" self.__wrapped_init__(*args, **kwargs) _process_dependencies(self) def wrapped(cls): """Note the required dependencies on the object for later injection. The dependencies of the parent class are combined with that of the child class to create a new set of dependencies. """ existing_dependencies = getattr(cls, '_dependencies', set()) cls._dependencies = existing_dependencies.union(dependencies) if not hasattr(cls, '__wrapped_init__'): cls.__wrapped_init__ = cls.__init__ cls.__init__ = wrapper return cls return wrapped def optional(*dependencies): """'optional' is the same as 'requires', except that the dependencies are optional - if no provider is available, the attributes will be set to None. """ def wrapper(self, *args, **kwargs): """Inject each dependency from the registry.""" self.__wrapped_init__(*args, **kwargs) _process_dependencies(self) def wrapped(cls): """Note the optional dependencies on the object for later injection. The dependencies of the parent class are combined with that of the child class to create a new set of dependencies. """ existing_optionals = getattr(cls, '_optionals', set()) cls._optionals = existing_optionals.union(dependencies) if not hasattr(cls, '__wrapped_init__'): cls.__wrapped_init__ = cls.__init__ cls.__init__ = wrapper return cls return wrapped def resolve_future_dependencies(provider_name=None): """'resolve_future_dependencies' forces injection of all dependencies. Before this function is called, circular dependencies may not have been injected. This function should be called only once, after all global providers are registered. If an object needs to be created after this call, it must not have circular dependencies. If any required dependencies are unresolvable, this function will raise an UnresolvableDependencyException. Outside of this module, this function should be called with no arguments; the optional argument is used internally, and should be treated as an implementation detail. """ new_providers = dict() if provider_name: # A provider was registered, so take care of any objects depending on # it. targets = _future_dependencies.pop(provider_name, []) targets.extend(_future_optionals.pop(provider_name, [])) for target in targets: setattr(target, provider_name, REGISTRY[provider_name]) return # Resolve optional dependencies, sets the attribute to None if there's no # provider registered. for dependency, targets in six.iteritems(_future_optionals.copy()): provider = REGISTRY.get(dependency) if provider is None: factory = _factories.get(dependency) if factory: provider = factory() REGISTRY[dependency] = provider new_providers[dependency] = provider for target in targets: setattr(target, dependency, provider) # Resolve future dependencies, raises UnresolvableDependencyException if # there's no provider registered. try: for dependency, targets in six.iteritems(_future_dependencies.copy()): if dependency not in REGISTRY: # a Class was registered that could fulfill the dependency, but # it has not yet been initialized. factory = _factories.get(dependency) if factory: provider = factory() REGISTRY[dependency] = provider new_providers[dependency] = provider else: raise UnresolvableDependencyException(dependency) for target in targets: setattr(target, dependency, REGISTRY[dependency]) finally: _future_dependencies.clear() return new_providers def reset(): """Reset the registry of providers. This is useful for unit testing to ensure that tests don't use providers from previous tests. """ REGISTRY.clear() _future_dependencies.clear() _future_optionals.clear() keystone-2014.1/keystone/common/base64utils.py0000664000175400017540000003150712323716267022467 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """ Python provides the base64 module as a core module but this is mostly limited to encoding and decoding base64 and it's variants. It is often useful to be able to perform other operations on base64 text. This module is meant to be used in conjunction with the core base64 module. Standarized base64 is defined in RFC-4648 "The Base16, Base32, and Base64 Data Encodings". This module provides the following base64 utility functionality: * tests if text is valid base64 * filter formatting from base64 * convert base64 between different alphabets * Handle padding issues - test if base64 is padded - removes padding - restores padding * wraps base64 text into formatted blocks - via iterator - return formatted string """ import re import string import six from six.moves import urllib from keystone.openstack.common.gettextutils import _ class InvalidBase64Error(ValueError): pass base64_alphabet_re = re.compile(r'^[^A-Za-z0-9+/=]+$') base64url_alphabet_re = re.compile(r'^[^A-Za-z0-9---_=]+$') base64_non_alphabet_re = re.compile(r'[^A-Za-z0-9+/=]+') base64url_non_alphabet_re = re.compile(r'[^A-Za-z0-9---_=]+') _strip_formatting_re = re.compile(r'\s+') _base64_to_base64url_trans = string.maketrans('+/', '-_') _base64url_to_base64_trans = string.maketrans('-_', '+/') def is_valid_base64(text): """Test if input text can be base64 decoded. :param text: input base64 text :type text: string :returns: bool -- True if text can be decoded as base64, False otherwise """ text = filter_formatting(text) if base64_non_alphabet_re.search(text): return False try: return base64_is_padded(text) except InvalidBase64Error: return False def is_valid_base64url(text): """Test if input text can be base64url decoded. :param text: input base64 text :type text: string :returns: bool -- True if text can be decoded as base64url, False otherwise """ text = filter_formatting(text) if base64url_non_alphabet_re.search(text): return False try: return base64_is_padded(text) except InvalidBase64Error: return False def filter_formatting(text): """Return base64 text without any formatting, just the base64. Base64 text is often formatted with whitespace, line endings, etc. This function strips out any formatting, the result will contain only base64 characters. Note, this function does not filter out all non-base64 alphabet characters, it only removes characters used for formatting. :param text: input text to filter :type text: string :returns: string -- filtered text without formatting """ return _strip_formatting_re.sub('', text) def base64_to_base64url(text): """Convert base64 text to base64url text. base64url text is designed to be safe for use in filenames and URL's. It is defined in RFC-4648 Section 5. base64url differs from base64 in the last two alphabet characters at index 62 and 63, these are sometimes referred as the altchars. The '+' character at index 62 is replaced by '-' (hyphen) and the '/' character at index 63 is replaced by '_' (underscore). This function only translates the altchars, non-alphabet characters are not filtered out. WARNING:: base64url continues to use the '=' pad character which is NOT URL safe. RFC-4648 suggests two alternate methods to deal with this: percent-encode percent-encode the pad character (e.g. '=' becomes '%3D'). This makes the base64url text fully safe. But percent-enconding has the downside of requiring percent-decoding prior to feeding the base64url text into a base64url decoder since most base64url decoders do not recognize %3D as a pad character and most decoders require correct padding. no-padding padding is not strictly necessary to decode base64 or base64url text, the pad can be computed from the input text length. However many decoders demand padding and will consider non-padded text to be malformed. If one wants to omit the trailing pad character(s) for use in URL's it can be added back using the base64_assure_padding() function. This function makes no decisions about which padding methodolgy to use. One can either call base64_strip_padding() to remove any pad characters (restoring later with base64_assure_padding()) or call base64url_percent_encode() to percent-encode the pad characters. :param text: input base64 text :type text: string :returns: string -- base64url text """ return text.translate(_base64_to_base64url_trans) def base64url_to_base64(text): """Convert base64url text to base64 text. See base64_to_base64url() for a description of base64url text and it's issues. This function does NOT handle percent-encoded pad characters, they will be left intact. If the input base64url text is percent-encoded you should call :param text: text in base64url alphabet :type text: string :returns: string -- text in base64 alphabet """ return text.translate(_base64url_to_base64_trans) def base64_is_padded(text, pad='='): """Test if the text is base64 padded. The input text must be in a base64 alphabet. The pad must be a single character. If the text has been percent-encoded (e.g. pad is the string '%3D') you must convert the text back to a base64 alphabet (e.g. if percent-encoded use the function base64url_percent_decode()). :param text: text containing ONLY characters in a base64 alphabet :type text: string :param pad: pad character (must be single character) (default: '=') :type pad: string :returns: bool -- True if padded, False otherwise :raises: ValueError, InvalidBase64Error """ if len(pad) != 1: raise ValueError(_('pad must be single character')) text_len = len(text) if text_len > 0 and text_len % 4 == 0: pad_index = text.find(pad) if pad_index >= 0 and pad_index < text_len - 2: raise InvalidBase64Error(_('text is multiple of 4, ' 'but pad "%s" occurs before ' '2nd to last char') % pad) if pad_index == text_len - 2 and text[-1] != pad: raise InvalidBase64Error(_('text is multiple of 4, ' 'but pad "%s" occurs before ' 'non-pad last char') % pad) return True if text.find(pad) >= 0: raise InvalidBase64Error(_('text is not a multiple of 4, ' 'but contains pad "%s"') % pad) return False def base64url_percent_encode(text): """Percent-encode base64url padding. The input text should only contain base64url alphabet characters. Any non-base64url alphabet characters will also be subject to percent-encoding. :param text: text containing ONLY characters in the base64url alphabet :type text: string :returns: string -- percent-encoded base64url text :raises: InvalidBase64Error """ if len(text) % 4 != 0: raise InvalidBase64Error(_('padded base64url text must be ' 'multiple of 4 characters')) return urllib.parse.quote(text) def base64url_percent_decode(text): """Percent-decode base64url padding. The input text should only contain base64url alphabet characters and the percent-encoded pad character. Any other percent-encoded characters will be subject to percent-decoding. :param text: base64url alphabet text :type text: string :returns: string -- percent-decoded base64url text """ decoded_text = urllib.parse.unquote(text) if len(decoded_text) % 4 != 0: raise InvalidBase64Error(_('padded base64url text must be ' 'multiple of 4 characters')) return decoded_text def base64_strip_padding(text, pad='='): """Remove padding from input base64 text. :param text: text containing ONLY characters in a base64 alphabet :type text: string :param pad: pad character (must be single character) (default: '=') :type pad: string :returns: string -- base64 text without padding :raises: ValueError """ if len(pad) != 1: raise ValueError(_('pad must be single character')) # Can't be padded if text is less than 4 characters. if len(text) < 4: return text if text[-1] == pad: if text[-2] == pad: return text[0:-2] else: return text[0:-1] else: return text def base64_assure_padding(text, pad='='): """Assure the input text ends with padding. Base64 text is normally expected to be a multple of 4 characters. Each 4 character base64 sequence produces 3 octets of binary data. If the binary data is not a multiple of 3 the base64 text is padded at the end with a pad character such that is is always a multple of 4. Padding is ignored and does not alter the binary data nor it's length. In some circumstances is is desirable to omit the padding character due to transport encoding conflicts. Base64 text can still be correctly decoded if the length of the base64 text (consisting only of characters in the desired base64 alphabet) is known, padding is not absolutely necessary. Some base64 decoders demand correct padding or one may wish to format RFC compliant base64, this function performs this action. Input is assumed to consist only of members of a base64 alphabet (i.e no whitepace). Iteration yields a sequence of lines. The line does NOT terminate with a line ending. Use the filter_formatting() function to assure the input text contains only the members of the alphabet. If the text ends with the pad it is assumed to already be padded. Otherwise the binary length is computed from the input text length and correct number of pad characters are appended. :param text: text containing ONLY characters in a base64 alphabet :type text: string :param pad: pad character (must be single character) (default: '=') :type pad: string :returns: string -- input base64 text with padding :raises: ValueError """ if len(pad) != 1: raise ValueError(_('pad must be single character')) if text.endswith(pad): return text n = len(text) % 4 if n == 0: return text n = 4 - n padding = pad * n return text + padding def base64_wrap_iter(text, width=64): """Fold text into lines of text with max line length. Input is assumed to consist only of members of a base64 alphabet (i.e no whitepace). Iteration yields a sequence of lines. The line does NOT terminate with a line ending. Use the filter_formatting() function to assure the input text contains only the members of the alphabet. :param text: text containing ONLY characters in a base64 alphabet :type text: string :param width: number of characters in each wrapped line (default: 64) :type width: int :returns: generator -- sequence of lines of base64 text. """ text = six.text_type(text) for x in six.moves.range(0, len(text), width): yield text[x:x + width] def base64_wrap(text, width=64): """Fold text into lines of text with max line length. Input is assumed to consist only of members of a base64 alphabet (i.e no whitepace). Fold the text into lines whose line length is width chars long, terminate each line with line ending (default is '\\n'). Return the wrapped text as a single string. Use the filter_formatting() function to assure the input text contains only the members of the alphabet. :param text: text containing ONLY characters in a base64 alphabet :type text: string :param width: number of characters in each wrapped line (default: 64) :type width: int :returns: string -- wrapped text. """ buf = six.StringIO() for line in base64_wrap_iter(text, width): buf.write(line) buf.write(u'\n') text = buf.getvalue() buf.close() return text keystone-2014.1/keystone/common/sql/0000775000175400017540000000000012323716511020531 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/sql/core.py0000664000175400017540000003257612323716267022060 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """SQL backends for the various services. Before using this module, call initialize(). This has to be done before CONF() because it sets up configuration options. """ import contextlib import functools from oslo.config import cfg import six import sqlalchemy as sql from sqlalchemy.ext import declarative from sqlalchemy.orm.attributes import flag_modified, InstrumentedAttribute from sqlalchemy import types as sql_types from keystone.common import utils from keystone import exception from keystone.openstack.common.db import exception as db_exception from keystone.openstack.common.db import options as db_options from keystone.openstack.common.db.sqlalchemy import models from keystone.openstack.common.db.sqlalchemy import session as db_session from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils CONF = cfg.CONF ModelBase = declarative.declarative_base() # For exporting to other modules Column = sql.Column Index = sql.Index String = sql.String Integer = sql.Integer Enum = sql.Enum ForeignKey = sql.ForeignKey DateTime = sql.DateTime IntegrityError = sql.exc.IntegrityError DBDuplicateEntry = db_exception.DBDuplicateEntry OperationalError = sql.exc.OperationalError NotFound = sql.orm.exc.NoResultFound Boolean = sql.Boolean Text = sql.Text UniqueConstraint = sql.UniqueConstraint PrimaryKeyConstraint = sql.PrimaryKeyConstraint joinedload = sql.orm.joinedload # Suppress flake8's unused import warning for flag_modified: flag_modified = flag_modified def initialize(): """Initialize the module.""" db_options.set_defaults( sql_connection="sqlite:///keystone.db", sqlite_db="keystone.db") def initialize_decorator(init): """Ensure that the length of string field do not exceed the limit. This decorator check the initialize arguments, to make sure the length of string field do not exceed the length limit, or raise a 'StringLengthExceeded' exception. Use decorator instead of inheritance, because the metaclass will check the __tablename__, primary key columns, etc. at the class definition. """ def initialize(self, *args, **kwargs): cls = type(self) for k, v in kwargs.items(): if hasattr(cls, k): attr = getattr(cls, k) if isinstance(attr, InstrumentedAttribute): column = attr.property.columns[0] if isinstance(column.type, String): if not isinstance(v, six.text_type): v = six.text_type(v) if column.type.length and \ column.type.length < len(v): raise exception.StringLengthExceeded( string=v, type=k, length=column.type.length) init(self, *args, **kwargs) return initialize ModelBase.__init__ = initialize_decorator(ModelBase.__init__) # Special Fields class JsonBlob(sql_types.TypeDecorator): impl = sql.Text def process_bind_param(self, value, dialect): return jsonutils.dumps(value) def process_result_value(self, value, dialect): return jsonutils.loads(value) class DictBase(models.ModelBase): attributes = [] @classmethod def from_dict(cls, d): new_d = d.copy() new_d['extra'] = dict((k, new_d.pop(k)) for k in six.iterkeys(d) if k not in cls.attributes and k != 'extra') return cls(**new_d) def to_dict(self, include_extra_dict=False): """Returns the model's attributes as a dictionary. If include_extra_dict is True, 'extra' attributes are literally included in the resulting dictionary twice, for backwards-compatibility with a broken implementation. """ d = self.extra.copy() for attr in self.__class__.attributes: d[attr] = getattr(self, attr) if include_extra_dict: d['extra'] = self.extra.copy() return d def __getitem__(self, key): if key in self.extra: return self.extra[key] return getattr(self, key) class ModelDictMixin(object): @classmethod def from_dict(cls, d): """Returns a model instance from a dictionary.""" return cls(**d) def to_dict(self): """Returns the model's attributes as a dictionary.""" names = (column.name for column in self.__table__.columns) return dict((name, getattr(self, name)) for name in names) _engine_facade = None def _get_engine_facade(): global _engine_facade if not _engine_facade: _engine_facade = db_session.EngineFacade.from_config( CONF.database.connection, CONF) return _engine_facade def cleanup(): global _engine_facade _engine_facade = None def get_engine(): return _get_engine_facade().get_engine() def get_session(expire_on_commit=False): return _get_engine_facade().get_session(expire_on_commit=expire_on_commit) @contextlib.contextmanager def transaction(expire_on_commit=False): """Return a SQLAlchemy session in a scoped transaction.""" session = get_session(expire_on_commit=expire_on_commit) with session.begin(): yield session def truncated(f): """Ensure list truncation is detected in Driver list entity methods. This is designed to wrap and sql Driver list_{entity} methods in order to calculate if the resultant list has been truncated. Provided a limit dict is found in the hints list, we increment the limit by one so as to ask the wrapped function for one more entity than the limit, and then once the list has been generated, we check to see if the original limit has been exceeded, in which case we truncate back to that limit and set the 'truncated' boolean to 'true' in the hints limit dict. """ @functools.wraps(f) def wrapper(self, hints, *args, **kwargs): if not hasattr(hints, 'get_limit'): raise exception.UnexpectedError( _('Cannot truncate a driver call without hints list as ' 'first parameter after self ')) limit_dict = hints.get_limit() if limit_dict is None: return f(self, hints, *args, **kwargs) # A limit is set, so ask for one more entry than we need list_limit = limit_dict['limit'] hints.set_limit(list_limit + 1) ref_list = f(self, hints, *args, **kwargs) # If we got more than the original limit then trim back the list and # mark it truncated. In both cases, make sure we set the limit back # to its original value. if len(ref_list) > list_limit: hints.set_limit(list_limit, truncated=True) return ref_list[:list_limit] else: hints.set_limit(list_limit) return ref_list return wrapper def _filter(model, query, hints): """Applies filtering to a query. :param model: the table model in question :param query: query to apply filters to :param hints: contains the list of filters yet to be satisfied. Any filters satisfied here will be removed so that the caller will know if any filters remain. :returns query: query, updated with any filters satisfied """ def inexact_filter(model, query, filter_, hints): """Applies an inexact filter to a query. :param model: the table model in question :param query: query to apply filters to :param filter_: the dict that describes this filter :param hints: contains the list of filters yet to be satisfied. Any filters satisfied here will be removed so that the caller will know if any filters remain. :returns query: query updated to add any inexact filters we could satisfy """ column_attr = getattr(model, filter_['name']) # TODO(henry-nash): Sqlalchemy 0.7 defaults to case insensitivity # so once we find a way of changing that (maybe on a call-by-call # basis), we can add support for the case sensitive versions of # the filters below. For now, these case sensitive versions will # be handled at the controller level. if filter_['case_sensitive']: return query if filter_['comparator'] == 'contains': query_term = column_attr.ilike('%%%s%%' % filter_['value']) elif filter_['comparator'] == 'startswith': query_term = column_attr.ilike('%s%%' % filter_['value']) elif filter_['comparator'] == 'endswith': query_term = column_attr.ilike('%%%s' % filter_['value']) else: # It's a filter we don't understand, so let the caller # work out if they need to do something with it. return query hints.remove(filter_) return query.filter(query_term) def exact_filter(model, filter_, cumulative_filter_dict, hints): """Applies an exact filter to a query. :param model: the table model in question :param filter_: the dict that describes this filter :param cumulative_filter_dict: a dict that describes the set of exact filters built up so far :param hints: contains the list of filters yet to be satisfied. Any filters satisfied here will be removed so that the caller will know if any filters remain. :returns: updated cumulative dict """ key = filter_['name'] if isinstance(getattr(model, key).property.columns[0].type, sql.types.Boolean): cumulative_filter_dict[key] = ( utils.attr_as_boolean(filter_['value'])) else: cumulative_filter_dict[key] = filter_['value'] hints.remove(filter_) return cumulative_filter_dict filter_dict = {} for filter_ in hints.filters(): # TODO(henry-nash): Check if name is valid column, if not skip if filter_['comparator'] == 'equals': filter_dict = exact_filter(model, filter_, filter_dict, hints) else: query = inexact_filter(model, query, filter_, hints) # Apply any exact filters we built up if filter_dict: query = query.filter_by(**filter_dict) return query def _limit(query, hints): """Applies a limit to a query. :param query: query to apply filters to :param hints: contains the list of filters and limit details. :returns updated query """ # NOTE(henry-nash): If we were to implement pagination, then we # we would expand this method to support pagination and limiting. # If we satisfied all the filters, set an upper limit if supplied list_limit = hints.get_limit() if list_limit: query = query.limit(list_limit['limit']) return query def filter_limit_query(model, query, hints): """Applies filtering and limit to a query. :param model: table model :param query: query to apply filters to :param hints: contains the list of filters and limit details. This may be None, indicating that there are no filters or limits to be applied. If it's not None, then any filters satisfied here will be removed so that the caller will know if any filters remain. :returns: updated query """ if hints is None: return query # First try and satisfy any filters query = _filter(model, query, hints) # NOTE(henry-nash): Any unsatisfied filters will have been left in # the hints list for the controller to handle. We can only try and # limit here if all the filters are already satisfied since, if not, # doing so might mess up the final results. If there are still # unsatisfied filters, we have to leave any limiting to the controller # as well. if not hints.filters(): return _limit(query, hints) else: return query def handle_conflicts(conflict_type='object'): """Converts select sqlalchemy exceptions into HTTP 409 Conflict.""" def decorator(method): @functools.wraps(method) def wrapper(*args, **kwargs): try: return method(*args, **kwargs) except db_exception.DBDuplicateEntry as e: raise exception.Conflict(type=conflict_type, details=six.text_type(e)) except db_exception.DBError as e: # TODO(blk-u): inspecting inner_exception breaks encapsulation; # oslo.db should provide exception we need. if isinstance(e.inner_exception, IntegrityError): raise exception.Conflict(type=conflict_type, details=six.text_type(e)) raise return wrapper return decorator keystone-2014.1/keystone/common/sql/migrate_repo/0000775000175400017540000000000012323716511023206 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/sql/migrate_repo/versions/0000775000175400017540000000000012323716511025056 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/sql/migrate_repo/versions/037_add_region_table.py0000664000175400017540000000234512323716267031277 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine region_table = sql.Table( 'region', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('description', sql.String(255), nullable=False), sql.Column('parent_region_id', sql.String(64), nullable=True), sql.Column('extra', sql.Text())) region_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine region = sql.Table('region', meta, autoload=True) region.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/common/sql/migrate_repo/versions/041_add_remaining_uses_count_to_trusts.py0000664000175400017540000000303712323716267035205 0ustar jenkinsjenkins00000000000000# Copyright (c) 2014 Matthieu Huin # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy def downgrade_trust_table_with_column_drop(meta, migrate_engine): trust_table = sqlalchemy.Table('trust', meta, autoload=True) # delete trusts with a limited use count, we are downgrading so uses # will not be tracked anymore. d = trust_table.delete(trust_table.c.remaining_uses >= 0) d.execute() trust_table.drop_column('remaining_uses') def upgrade_trust_table(meta, migrate_engine): trust_table = sqlalchemy.Table('trust', meta, autoload=True) trust_table.create_column(sqlalchemy.Column('remaining_uses', sqlalchemy.Integer(), nullable=True)) def upgrade(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine upgrade_trust_table(meta, migrate_engine) def downgrade(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine downgrade_trust_table_with_column_drop(meta, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/005_set_utf8_character_set.py0000664000175400017540000000357612323716272032463 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from sqlalchemy import MetaData def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = MetaData() meta.bind = migrate_engine if migrate_engine.name == "mysql": tables = ['tenant', 'user', 'role', 'token', 'service', 'metadata', 'ec2_credential', 'endpoint', 'user_tenant_membership'] sql = "SET foreign_key_checks = 0;" for table in tables: sql += "ALTER TABLE %s CONVERT TO CHARACTER SET utf8;" % table sql += "SET foreign_key_checks = 1;" sql += "ALTER DATABASE %s DEFAULT CHARACTER SET utf8;" \ % migrate_engine.url.database migrate_engine.execute(sql) def downgrade(migrate_engine): # Operations to reverse the above upgrade go here. if migrate_engine.name == "mysql": tables = ['tenant', 'user', 'role', 'token', 'service', 'metadata', 'ec2_credential', 'endpoint', 'user_tenant_membership'] sql = "SET foreign_key_checks = 0;" for table in tables: sql += "ALTER TABLE %s CONVERT TO CHARACTER SET latin1;" % table sql += "SET foreign_key_checks = 1;" sql += "ALTER DATABASE %s DEFAULT CHARACTER SET latin1;" \ % migrate_engine.url.database keystone-2014.1/keystone/common/sql/migrate_repo/versions/018_add_trust_tables.py0000664000175400017540000000450612323716272031354 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine sql.Table('user', meta, autoload=True) sql.Table('role', meta, autoload=True) sql.Table('project', meta, autoload=True) trust_table = sql.Table( 'trust', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('trustor_user_id', sql.String(64), unique=False, nullable=False,), sql.Column('trustee_user_id', sql.String(64), unique=False, nullable=False), sql.Column('project_id', sql.String(64), unique=False, nullable=True), sql.Column("impersonation", sql.types.Boolean, nullable=False), sql.Column("deleted_at", sql.types.DateTime, nullable=True), sql.Column("expires_at", sql.types.DateTime, nullable=True), sql.Column('extra', sql.Text())) trust_table.create(migrate_engine, checkfirst=True) trust_role_table = sql.Table( 'trust_role', meta, sql.Column('trust_id', sql.String(64), primary_key=True, nullable=False), sql.Column('role_id', sql.String(64), primary_key=True, nullable=False)) trust_role_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine # Operations to reverse the above upgrade go here. for table_name in ['trust_role', 'trust']: table = sql.Table(table_name, meta, autoload=True) table.drop() keystone-2014.1/keystone/common/sql/migrate_repo/versions/029_update_assignment_metadata.py0000664000175400017540000000761612323716272033412 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json import sqlalchemy as sql def build_update(table_name, upgrade_table, row, values): if table_name == 'user_project_metadata': update = upgrade_table.update().where( upgrade_table.c.user_id == row.user_id).where( upgrade_table.c.project_id == row.project_id).values(values) elif table_name == 'group_project_metadata': update = upgrade_table.update().where( upgrade_table.c.group_id == row.group_id).where( upgrade_table.c.project_id == row.project_id).values(values) elif table_name == 'user_domain_metadata': update = upgrade_table.update().where( upgrade_table.c.user_id == row.user_id).where( upgrade_table.c.domain_id == row.domain_id).values(values) else: update = upgrade_table.update().where( upgrade_table.c.group_id == row.group_id).where( upgrade_table.c.domain_id == row.domain_id).values(values) return update def upgrade_grant_table(meta, migrate_engine, session, table_name): # Convert the roles component of the metadata from a list # of ids to a list of dicts def list_to_dict_list(metadata): json_metadata = json.loads(metadata) if 'roles' in json_metadata: json_metadata['roles'] = ( [{'id': x} for x in json_metadata['roles']]) return json.dumps(json_metadata) upgrade_table = sql.Table(table_name, meta, autoload=True) for assignment in session.query(upgrade_table): values = {'data': list_to_dict_list(assignment.data)} update = build_update(table_name, upgrade_table, assignment, values) migrate_engine.execute(update) def downgrade_grant_table(meta, migrate_engine, session, table_name): # Convert the roles component of the metadata from a list # of dicts to a simple list of ids. Any inherited roles are deleted # since they would have no meaning def dict_list_to_list(metadata): json_metadata = json.loads(metadata) if 'roles' in json_metadata: json_metadata['roles'] = ([x['id'] for x in json_metadata['roles'] if 'inherited_to' not in x]) return json.dumps(json_metadata) downgrade_table = sql.Table(table_name, meta, autoload=True) for assignment in session.query(downgrade_table): values = {'data': dict_list_to_list(assignment.data)} update = build_update(table_name, downgrade_table, assignment, values) migrate_engine.execute(update) def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine session = sql.orm.sessionmaker(bind=migrate_engine)() for grant_table in ['user_project_metadata', 'user_domain_metadata', 'group_project_metadata', 'group_domain_metadata']: upgrade_grant_table(meta, migrate_engine, session, grant_table) session.commit() session.close() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine session = sql.orm.sessionmaker(bind=migrate_engine)() for grant_table in ['user_project_metadata', 'user_domain_metadata', 'group_project_metadata', 'group_domain_metadata']: downgrade_grant_table(meta, migrate_engine, session, grant_table) session.commit() session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/024_add_index_to_expires.py0000664000175400017540000000210612323716272032200 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_expires', token.c.expires) idx.create(migrate_engine) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_expires', token.c.expires) idx.drop(migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/040_drop_grant_tables.py0000664000175400017540000000635012323716267031520 0ustar jenkinsjenkins00000000000000# Copyright 2014 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql USER_PROJECT_TABLE = 'user_project_metadata' GROUP_PROJECT_TABLE = 'group_project_metadata' USER_DOMAIN_TABLE = 'user_domain_metadata' GROUP_DOMAIN_TABLE = 'group_domain_metadata' GRANT_TABLES = [USER_PROJECT_TABLE, USER_DOMAIN_TABLE, GROUP_PROJECT_TABLE, GROUP_DOMAIN_TABLE] def recreate_grant_tables(meta, migrate_engine): sql.Table('user', meta, autoload=True) sql.Table('group', meta, autoload=True) sql.Table('project', meta, autoload=True) sql.Table('domain', meta, autoload=True) user_project_metadata_table = sql.Table( USER_PROJECT_TABLE, meta, sql.Column( 'user_id', sql.String(64), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True), sql.Column('data', sql.Text())) user_project_metadata_table.create(migrate_engine, checkfirst=True) group_project_metadata_table = sql.Table( GROUP_PROJECT_TABLE, meta, sql.Column( 'group_id', sql.String(64), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True), sql.Column('data', sql.Text())) group_project_metadata_table.create(migrate_engine, checkfirst=True) user_domain_metadata_table = sql.Table( USER_DOMAIN_TABLE, meta, sql.Column( 'user_id', sql.String(64), primary_key=True), sql.Column( 'domain_id', sql.String(64), sql.ForeignKey('domain.id'), primary_key=True), sql.Column('data', sql.Text())) user_domain_metadata_table.create(migrate_engine, checkfirst=True) group_domain_metadata_table = sql.Table( GROUP_DOMAIN_TABLE, meta, sql.Column( 'group_id', sql.String(64), primary_key=True), sql.Column( 'domain_id', sql.String(64), sql.ForeignKey('domain.id'), primary_key=True), sql.Column('data', sql.Text())) group_domain_metadata_table.create(migrate_engine, checkfirst=True) def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine for table_name in GRANT_TABLES: grant_table = sql.Table(table_name, meta, autoload=True) grant_table.drop(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine recreate_grant_tables(meta, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/014_add_group_tables.py0000664000175400017540000000601712323716272031322 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine sql.Table('domain', meta, autoload=True) group_table = sql.Table( 'group', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=False), sql.Column('name', sql.String(64), nullable=False), sql.Column('description', sql.Text()), sql.Column('extra', sql.Text()), sql.UniqueConstraint('domain_id', 'name')) group_table.create(migrate_engine, checkfirst=True) sql.Table('user', meta, autoload=True) user_group_membership_table = sql.Table( 'user_group_membership', meta, sql.Column( 'user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column( 'group_id', sql.String(64), sql.ForeignKey('group.id'), primary_key=True)) user_group_membership_table.create(migrate_engine, checkfirst=True) sql.Table('tenant', meta, autoload=True) group_project_metadata_table = sql.Table( 'group_project_metadata', meta, sql.Column( 'group_id', sql.String(64), sql.ForeignKey('group.id'), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('tenant.id'), primary_key=True), sql.Column('data', sql.Text())) group_project_metadata_table.create(migrate_engine, checkfirst=True) group_domain_metadata_table = sql.Table( 'group_domain_metadata', meta, sql.Column( 'group_id', sql.String(64), sql.ForeignKey('group.id'), primary_key=True), sql.Column( 'domain_id', sql.String(64), sql.ForeignKey('domain.id'), primary_key=True), sql.Column('data', sql.Text())) group_domain_metadata_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine tables = ['user_group_membership', 'group_project_metadata', 'group_domain_metadata', 'group'] for t in tables: table = sql.Table(t, meta, autoload=True) table.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/common/sql/migrate_repo/versions/021_add_trust_to_token.py0000664000175400017540000000521012323716272031707 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy from sqlalchemy import exc def downgrade_token_table_with_column_drop(meta, migrate_engine): token_table = sqlalchemy.Table('token', meta, autoload=True) #delete old tokens, as the format has changed. #We don't guarantee that existing tokens will be #usable after a migration token_table.delete() token_table.drop_column( sqlalchemy.Column('trust_id', sqlalchemy.String(64), nullable=True)) token_table.drop_column( sqlalchemy.Column('user_id', sqlalchemy.String(64))) def create_column_forgiving(migrate_engine, table, column): try: table.create_column(column) except exc.OperationalError as e: if (e.args[0].endswith('duplicate column name: %s' % column.name) and migrate_engine.name == "sqlite"): #sqlite does not drop columns, so if we have already #done a downgrade and are now upgrading, we will hit #this: the SQLite driver previously reported success #dropping the columns but it hasn't. pass else: raise def upgrade_token_table(meta, migrate_engine): #delete old tokens, as the format has changed. #The existing tokens will not #support some of the list functions token_table = sqlalchemy.Table('token', meta, autoload=True) token_table.delete() create_column_forgiving( migrate_engine, token_table, sqlalchemy.Column('trust_id', sqlalchemy.String(64), nullable=True)) create_column_forgiving( migrate_engine, token_table, sqlalchemy.Column('user_id', sqlalchemy.String(64))) def upgrade(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine upgrade_token_table(meta, migrate_engine) def downgrade(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine downgrade_token_table_with_column_drop(meta, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/036_token_drop_valid_index.py0000664000175400017540000000212312323716272032534 0ustar jenkinsjenkins00000000000000# Copyright 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_valid', token.c.valid) idx.drop(migrate_engine) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_valid', token.c.valid) idx.create(migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py0000664000175400017540000000653612323716272033672 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json import sqlalchemy as sql from keystone import config CONF = config.CONF def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine sql.Table('user', meta, autoload=True) sql.Table('role', meta, autoload=True) sql.Table('project', meta, autoload=True) new_metadata_table = sql.Table('user_project_metadata', meta, autoload=True) old_metadata_table = sql.Table('metadata', meta, autoload=True) session = sql.orm.sessionmaker(bind=migrate_engine)() for metadata in session.query(old_metadata_table): data = json.loads(metadata.data) if config.CONF.member_role_id not in metadata.data: data['roles'].append(config.CONF.member_role_id) r = session.query(new_metadata_table).filter_by( user_id=metadata.user_id, project_id=metadata.tenant_id).first() if r is not None: # roles should be the union of the two role lists old_roles = data['roles'] new_roles = json.loads(r.data)['roles'] data['roles'] = list(set(old_roles) | set(new_roles)) q = new_metadata_table.update().where( new_metadata_table.c.user_id == metadata.user_id).where( new_metadata_table.c.project_id == metadata.tenant_id).values(data=json.dumps(data)) else: q = new_metadata_table.insert().values( user_id=metadata.user_id, project_id=metadata.tenant_id, data=json.dumps(data)) session.execute(q) session.commit() old_metadata_table.drop() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine sql.Table('user', meta, autoload=True) sql.Table('project', meta, autoload=True) metadata_table = sql.Table( 'metadata', meta, sql.Column( u'user_id', sql.String(64), primary_key=True), sql.Column( u'tenant_id', sql.String(64), primary_key=True), sql.Column('data', sql.Text())) metadata_table.create(migrate_engine, checkfirst=True) user_project_metadata_table = sql.Table( 'user_project_metadata', meta, autoload=True) metadata_table = sql.Table( 'metadata', meta, autoload=True) session = sql.orm.sessionmaker(bind=migrate_engine)() for metadata in session.query(user_project_metadata_table): if 'roles' in metadata: metadata_table.insert().values( user_id=metadata.user_id, tenant_id=metadata.project_id) session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/023_drop_credential_constraints.py0000664000175400017540000000321512323716272033606 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy from keystone.common.sql import migration_helpers def list_constraints(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine user_table = sqlalchemy.Table('user', meta, autoload=True) proj_table = sqlalchemy.Table('project', meta, autoload=True) cred_table = sqlalchemy.Table('credential', meta, autoload=True) constraints = [{'table': cred_table, 'fk_column': 'user_id', 'ref_column': user_table.c.id}, {'table': cred_table, 'fk_column': 'project_id', 'ref_column': proj_table.c.id}] return constraints def upgrade(migrate_engine): # SQLite does not support constraints, and querying the constraints # raises an exception if migrate_engine.name == 'sqlite': return migration_helpers.remove_constraints(list_constraints(migrate_engine)) def downgrade(migrate_engine): if migrate_engine.name == 'sqlite': return migration_helpers.add_constraints(list_constraints(migrate_engine)) keystone-2014.1/keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py0000664000175400017540000000543612323716272031443 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine domain_table = sql.Table( 'domain', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('enabled', sql.Boolean, nullable=False, default=True), sql.Column('extra', sql.Text())) domain_table.create(migrate_engine, checkfirst=True) sql.Table('user', meta, autoload=True) user_domain_metadata_table = sql.Table( 'user_domain_metadata', meta, sql.Column( 'user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column( 'domain_id', sql.String(64), sql.ForeignKey('domain.id'), primary_key=True), sql.Column('data', sql.Text())) user_domain_metadata_table.create(migrate_engine, checkfirst=True) sql.Table('tenant', meta, autoload=True) credential_table = sql.Table( 'credential', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('user_id', sql.String(64), sql.ForeignKey('user.id'), nullable=False), sql.Column('project_id', sql.String(64), sql.ForeignKey('tenant.id')), sql.Column('blob', sql.Text(), nullable=False), sql.Column('type', sql.String(255), nullable=False), sql.Column('extra', sql.Text())) credential_table.create(migrate_engine, checkfirst=True) role = sql.Table('role', meta, autoload=True) extra = sql.Column('extra', sql.Text()) role.create_column(extra) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine role = sql.Table('role', meta, autoload=True) role.drop_column('extra') tables = ['user_domain_metadata', 'credential', 'domain'] for t in tables: table = sql.Table(t, meta, autoload=True) table.drop(migrate_engine, checkfirst=True) ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000keystone-2014.1/keystone/common/sql/migrate_repo/versions/034_add_default_project_id_column_to_user.pykeystone-2014.1/keystone/common/sql/migrate_repo/versions/034_add_default_project_id_column_to_user.0000664000175400017540000000742512323716272035234 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json import sqlalchemy as sql from sqlalchemy.orm import sessionmaker def migrate_default_project_from_extra_json(meta, migrate_engine): user_table = sql.Table('user', meta, autoload=True) user_list = list(user_table.select().execute()) session = sessionmaker(bind=migrate_engine)() for user in user_list: try: data = json.loads(user.extra) default_project_id = data.pop('default_project_id', None) v2_tenant_id = data.pop('tenantId', None) alt_v2_tenant_id = data.pop('tenant_id', None) except (ValueError, TypeError): # NOTE(morganfainberg): Somehow we have non-json data here. This # is a broken user, but it was broken beforehand. Cleaning it up # is not in the scope of this migration. continue values = {} if default_project_id is not None: values['default_project_id'] = default_project_id elif v2_tenant_id is not None: values['default_project_id'] = v2_tenant_id elif alt_v2_tenant_id is not None: values['default_project_id'] = alt_v2_tenant_id if 'default_project_id' in values: values['extra'] = json.dumps(data) update = user_table.update().where( user_table.c.id == user['id']).values(values) migrate_engine.execute(update) session.commit() session.close() def migrate_default_project_to_extra_json(meta, migrate_engine): user_table = sql.Table('user', meta, autoload=True) user_list = list(user_table.select().execute()) session = sessionmaker(bind=migrate_engine)() for user in user_list: try: data = json.loads(user.extra) except (ValueError, TypeError): # NOTE(morganfainberg): Somehow we have non-json data here. This # is a broken user, but it was broken beforehand. Cleaning it up # is not in the scope of this migration. continue # NOTE(morganfainberg): We don't really know what the original 'extra' # property was here. Populate all of the possible variants we may have # originally used. if user.default_project_id is not None: data['default_project_id'] = user.default_project_id data['tenantId'] = user.default_project_id data['tenant_id'] = user.default_project_id values = {'extra': json.dumps(data)} update = user_table.update().where( user_table.c.id == user.id).values(values) migrate_engine.execute(update) session.commit() session.close() def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine user_table = sql.Table('user', meta, autoload=True) default_project_id = sql.Column('default_project_id', sql.String(64)) user_table.create_column(default_project_id) migrate_default_project_from_extra_json(meta, migrate_engine) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine migrate_default_project_to_extra_json(meta, migrate_engine) user_table = sql.Table('user', meta, autoload=True) user_table.drop_column('default_project_id') keystone-2014.1/keystone/common/sql/migrate_repo/versions/003_token_valid.py0000664000175400017540000000245612323716272030324 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack LLC # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) # creating the column immediately with nullable=False fails with # PostgreSQL (LP 1068181), so do it in two steps instead valid = sql.Column( 'valid', sql.Boolean(), sql.ColumnDefault(True), nullable=True) valid.create(token, populate_default=True) valid.alter(type=sql.Boolean(), default=True, nullable=False) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) token.drop_column('valid') keystone-2014.1/keystone/common/sql/migrate_repo/versions/032_username_length.py0000664000175400017540000000321612323716272031202 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql from sqlalchemy.orm import sessionmaker def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine user_table = sql.Table('user', meta, autoload=True) user_table.c.name.alter(type=sql.String(255)) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine user_table = sql.Table('user', meta, autoload=True) if migrate_engine.name != 'mysql': # NOTE(aloga): sqlite does not enforce length on the # VARCHAR types: http://www.sqlite.org/faq.html#q9 # postgresql and DB2 do not truncate. maker = sessionmaker(bind=migrate_engine) session = maker() for user in session.query(user_table).all(): values = {'name': user.name[:64]} update = (user_table.update(). where(user_table.c.id == user.id). values(values)) migrate_engine.execute(update) session.commit() session.close() user_table.c.name.alter(type=sql.String(64)) ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000keystone-2014.1/keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.pykeystone-2014.1/keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentia0000664000175400017540000001015512323716272035160 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql from keystone.common import utils from keystone import exception from keystone.openstack.common.gettextutils import _ def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine credential_table = sql.Table('credential', meta, autoload=True) ec2_cred_table = sql.Table('ec2_credential', meta, autoload=True) session = sql.orm.sessionmaker(bind=migrate_engine)() insert = credential_table.insert() for ec2credential in session.query(ec2_cred_table): cred_exist = check_credential_exists(ec2credential, credential_table, session) if not cred_exist: credential = utils.convert_ec2_to_v3_credential(ec2credential) insert.execute(credential) session.commit() session.close() ec2_cred_table.drop() def check_credential_exists(ec2credential, credential_table, session): credential = session.query(credential_table).filter_by( id=utils.hash_access_key(ec2credential.access)).first() if credential is None: return False blob = utils.get_blob_from_credential(credential) # check if credential with same access key but different # secret key already exists in credential table. # If exists raise an exception if blob['secret'] != ec2credential.secret: msg = _('Credential %(access)s already exists with different secret' ' in %(table)s table') message = msg % {'access': ec2credential.access, 'table': credential_table.name} raise exception.Conflict(type='credential', details=message) # check if credential with same access and secret key but # associated with a different project exists. If exists raise # an exception elif credential.project_id is not None and ( credential.project_id != ec2credential.tenant_id): msg = _('Credential %(access)s already exists with different project' ' in %(table)s table') message = msg % {'access': ec2credential.access, 'table': credential_table.name} raise exception.Conflict(type='credential', details=message) # if credential with same access and secret key and not associated # with any projects already exists in the credential table, then # return true. else: return True def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine session = sql.orm.sessionmaker(bind=migrate_engine)() ec2_credential_table = sql.Table( 'ec2_credential', meta, sql.Column('access', sql.String(64), primary_key=True), sql.Column('secret', sql.String(64)), sql.Column('user_id', sql.String(64)), sql.Column('tenant_id', sql.String(64)), mysql_engine='InnoDB', mysql_charset='utf8') ec2_credential_table.create(migrate_engine, checkfirst=True) credential_table = sql.Table('credential', meta, autoload=True) insert = ec2_credential_table.insert() for credential in session.query(credential_table).filter( sql.and_(credential_table.c.type == 'ec2', credential_table.c.project_id is not None)).all(): ec2_credential = utils.convert_v3_to_ec2_credential(credential) insert.execute(ec2_credential) session.commit() session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py0000664000175400017540000000460212323716272032374 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql from keystone.common.sql import migration_helpers def upgrade(migrate_engine): """Replace API-version specific endpoint tables with one based on v3.""" meta = sql.MetaData() meta.bind = migrate_engine legacy_table = sql.Table('endpoint_v2', meta, autoload=True) legacy_table.drop() new_table = sql.Table('endpoint_v3', meta, autoload=True) renames = {'endpoint': new_table} service_table = sql.Table('service', meta, autoload=True) constraints = [{'table': new_table, 'fk_column': 'service_id', 'ref_column': service_table.c.id}] migration_helpers.rename_tables_with_constraints(renames, constraints, migrate_engine) def downgrade(migrate_engine): """Create API-version specific endpoint tables.""" meta = sql.MetaData() meta.bind = migrate_engine new_table = sql.Table('endpoint', meta, autoload=True) renames = {'endpoint_v3': new_table} service_table = sql.Table('service', meta, autoload=True) constraints = [{'table': new_table, 'fk_column': 'service_id', 'ref_column': service_table.c.id}] migration_helpers.rename_tables_with_constraints(renames, constraints, migrate_engine) sql.Table('service', meta, autoload=True) legacy_table = sql.Table( 'endpoint_v2', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('region', sql.String(255)), sql.Column('service_id', sql.String(64), sql.ForeignKey('service.id'), nullable=False), sql.Column('extra', sql.Text())) legacy_table.create(migrate_engine, checkfirst=True) keystone-2014.1/keystone/common/sql/migrate_repo/versions/044_service_enabled.py0000664000175400017540000001106112323716267031140 0ustar jenkinsjenkins00000000000000# Copyright 2014 IBM Corp. # # 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. """Adds an `enabled` column to the `service` table. The enabled value for the `service` table was stored in the `extra` column as part of a JSON string. To upgrade, the `enabled` column is added with a default value of ``true``, then we check all the `extra` JSON for disabled and set the value to ``false`` for those. Downgrade is essentially the opposite -- we update the JSON with ``"enabled": false`` for any services that are disabled and drop the `enabled` column. """ import sqlalchemy as sql from sqlalchemy.orm import sessionmaker from keystone.openstack.common import jsonutils from keystone.openstack.common import strutils def _migrate_enabled_from_extra(migrate_engine, service_table): """Remove `enabled` from `extra`, put it in the `enabled` column.""" services = list(service_table.select().execute()) for service in services: extra_dict = jsonutils.loads(service.extra) if 'enabled' not in extra_dict: # `enabled` and `extra` are already as expected. continue enabled = extra_dict.pop('enabled') if enabled is None: enabled = True else: enabled = strutils.bool_from_string(enabled, default=True) new_values = { 'enabled': enabled, 'extra': jsonutils.dumps(extra_dict), } f = service_table.c.id == service.id update = service_table.update().where(f).values(new_values) migrate_engine.execute(update) def _migrate_enabled_to_extra(migrate_engine, service_table): """Get enabled value from 'enabled' column and put it in 'extra' JSON. Only put the enabled value to the 'extra' JSON if it's False, since the default is True. """ services = list(service_table.select().execute()) for service in services: if service.enabled: # Nothing to do since the service is enabled. continue extra_dict = jsonutils.loads(service.extra) extra_dict['enabled'] = False new_values = { 'extra': jsonutils.dumps(extra_dict), } f = service_table.c.id == service.id update = service_table.update().where(f).values(new_values) migrate_engine.execute(update) def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine service_table = sql.Table('service', meta, autoload=True) enabled_column = sql.Column('enabled', sql.Boolean, nullable=False, default=True, server_default='1') enabled_column.create(service_table) _migrate_enabled_from_extra(migrate_engine, service_table) def _downgrade_service_table_with_copy(meta, migrate_engine): # Used with databases that don't support dropping a column (e.g., sqlite). maker = sessionmaker(bind=migrate_engine) session = maker() session.execute('ALTER TABLE service RENAME TO orig_service;') service_table = sql.Table( 'service', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('type', sql.String(255)), sql.Column('extra', sql.Text())) service_table.create(migrate_engine, checkfirst=True) orig_service_table = sql.Table('orig_service', meta, autoload=True) for service in session.query(orig_service_table): new_values = { 'id': service.id, 'type': service.type, 'extra': service.extra, } session.execute('insert into service (id, type, extra) ' 'values ( :id, :type, :extra);', new_values) session.execute('drop table orig_service;') session.close() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine service_table = sql.Table('service', meta, autoload=True) _migrate_enabled_to_extra(migrate_engine, service_table) if migrate_engine.name == 'sqlite': meta.clear() _downgrade_service_table_with_copy(meta, migrate_engine) return service_table.c.enabled.drop() keystone-2014.1/keystone/common/sql/migrate_repo/versions/012_populate_endpoint_type.py0000664000175400017540000000655612323716272032624 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import json import uuid import sqlalchemy as sql from sqlalchemy import orm ENDPOINT_TYPES = ['public', 'internal', 'admin'] def upgrade(migrate_engine): """Split each legacy endpoint into separate records for each interface.""" meta = sql.MetaData() meta.bind = migrate_engine legacy_table = sql.Table('endpoint_v2', meta, autoload=True) new_table = sql.Table('endpoint_v3', meta, autoload=True) session = orm.sessionmaker(bind=migrate_engine)() for ref in session.query(legacy_table).all(): # pull urls out of extra extra = json.loads(ref.extra) urls = dict((i, extra.pop('%surl' % i)) for i in ENDPOINT_TYPES) for interface in ENDPOINT_TYPES: endpoint = { 'id': uuid.uuid4().hex, 'legacy_endpoint_id': ref.id, 'interface': interface, 'region': ref.region, 'service_id': ref.service_id, 'url': urls[interface], 'extra': json.dumps(extra), } insert = new_table.insert().values(endpoint) migrate_engine.execute(insert) session.commit() session.close() def downgrade(migrate_engine): """Re-create the v2 endpoints table based on v3 endpoints.""" meta = sql.MetaData() meta.bind = migrate_engine legacy_table = sql.Table('endpoint_v2', meta, autoload=True) new_table = sql.Table('endpoint_v3', meta, autoload=True) session = orm.sessionmaker(bind=migrate_engine)() for ref in session.query(new_table).all(): extra = json.loads(ref.extra) legacy_id = ref.legacy_endpoint_id or extra.get('legacy_endpoint_id') if not legacy_id: continue q = session.query(legacy_table) q = q.filter_by(id=legacy_id) legacy_ref = q.first() if legacy_ref: # We already have one, so just update the extra # attribute with the urls. extra = json.loads(legacy_ref.extra) extra['%surl' % ref.interface] = ref.url values = {'extra': json.dumps(extra)} update = legacy_table.update().\ where(legacy_table.c.id == legacy_ref.id).\ values(values) migrate_engine.execute(update) else: # This is the first one of this legacy ID, so # we can insert instead. extra = json.loads(ref.extra) extra['%surl' % ref.interface] = ref.url endpoint = { 'id': legacy_id, 'region': ref.region, 'service_id': ref.service_id, 'extra': json.dumps(extra), } insert = legacy_table.insert().values(endpoint) migrate_engine.execute(insert) session.commit() session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py0000664000175400017540000004620612323716272032220 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2013 IBM Corp. # # 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. """ Normalize for domain_id, i.e. ensure User and Project entities have the domain_id as a first class attribute. Both User and Project (as well as Group) entities are owned by a domain, which is implemented as each having a domain_id foreign key in their sql representation that points back to the respective domain in the domain table. This domain_id attribute should also be required (i.e. not nullable) Adding a non_nullable foreign key attribute to a table with existing data causes a few problems since not all DB engines support the ability to either control the triggering of integrity constraints or the ability to modify columns after they are created. To get round the above inconsistencies, two versions of the upgrade/downgrade functions are supplied, one for those engines that support dropping columns, and one for those that don't. For the latter we are forced to do table copy AND control the triggering of integrity constraints. """ import sqlalchemy as sql from sqlalchemy.orm import sessionmaker from keystone import config CONF = config.CONF def _disable_foreign_constraints(session, migrate_engine): if migrate_engine.name == 'mysql': session.execute('SET foreign_key_checks = 0;') def _enable_foreign_constraints(session, migrate_engine): if migrate_engine.name == 'mysql': session.execute('SET foreign_key_checks = 1;') def upgrade_user_table_with_copy(meta, migrate_engine, session): # We want to add the domain_id attribute to the user table. Since # it is non nullable and the table may have data, easiest way is # a table copy. Further, in order to keep foreign key constraints # pointing at the right table, we need to be able and do a table # DROP then CREATE, rather than ALTERing the name of the table. # First make a copy of the user table temp_user_table = sql.Table( 'temp_user', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text()), sql.Column('password', sql.String(128)), sql.Column('enabled', sql.Boolean, default=True)) temp_user_table.create(migrate_engine, checkfirst=True) user_table = sql.Table('user', meta, autoload=True) for user in session.query(user_table): session.execute('insert into temp_user (id, name, extra, ' 'password, enabled) ' 'values ( :id, :name, :extra, ' ':password, :enabled);', {'id': user.id, 'name': user.name, 'extra': user.extra, 'password': user.password, 'enabled': user.enabled}) # Now switch off constraints while we drop and then re-create the # user table, with the additional domain_id column _disable_foreign_constraints(session, migrate_engine) session.execute('drop table user;') # Need to create a new metadata stream since we are going to load a # different version of the user table meta2 = sql.MetaData() meta2.bind = migrate_engine sql.Table('domain', meta2, autoload=True) user_table = sql.Table( 'user', meta2, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), nullable=False), sql.Column('extra', sql.Text()), sql.Column("password", sql.String(128)), sql.Column("enabled", sql.Boolean, default=True), sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=False), sql.UniqueConstraint('domain_id', 'name')) user_table.create(migrate_engine, checkfirst=True) # Finally copy in the data from our temp table and then clean # up by deleting our temp table for user in session.query(temp_user_table): session.execute('insert into user (id, name, extra, ' 'password, enabled, domain_id) ' 'values ( :id, :name, :extra, ' ':password, :enabled, :domain_id);', {'id': user.id, 'name': user.name, 'extra': user.extra, 'password': user.password, 'enabled': user.enabled, 'domain_id': CONF.identity.default_domain_id}) _enable_foreign_constraints(session, migrate_engine) session.execute('drop table temp_user;') def upgrade_project_table_with_copy(meta, migrate_engine, session): # We want to add the domain_id attribute to the project table. Since # it is non nullable and the table may have data, easiest way is # a table copy. Further, in order to keep foreign key constraints # pointing at the right table, we need to be able and do a table # DROP then CREATE, rather than ALTERing the name of the table. # Fist make a copy of the project table temp_project_table = sql.Table( 'temp_project', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text()), sql.Column('description', sql.Text()), sql.Column('enabled', sql.Boolean, default=True)) temp_project_table.create(migrate_engine, checkfirst=True) project_table = sql.Table('project', meta, autoload=True) for project in session.query(project_table): session.execute('insert into temp_project (id, name, extra, ' 'description, enabled) ' 'values ( :id, :name, :extra, ' ':description, :enabled);', {'id': project.id, 'name': project.name, 'extra': project.extra, 'description': project.description, 'enabled': project.enabled}) # Now switch off constraints while we drop and then re-create the # project table, with the additional domain_id column _disable_foreign_constraints(session, migrate_engine) session.execute('drop table project;') # Need to create a new metadata stream since we are going to load a # different version of the project table meta2 = sql.MetaData() meta2.bind = migrate_engine sql.Table('domain', meta2, autoload=True) project_table = sql.Table( 'project', meta2, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), nullable=False), sql.Column('extra', sql.Text()), sql.Column('description', sql.Text()), sql.Column('enabled', sql.Boolean, default=True), sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=False), sql.UniqueConstraint('domain_id', 'name')) project_table.create(migrate_engine, checkfirst=True) # Finally copy in the data from our temp table and then clean # up by deleting our temp table for project in session.query(temp_project_table): session.execute('insert into project (id, name, extra, ' 'description, enabled, domain_id) ' 'values ( :id, :name, :extra, ' ':description, :enabled, :domain_id);', {'id': project.id, 'name': project.name, 'extra': project.extra, 'description': project.description, 'enabled': project.enabled, 'domain_id': CONF.identity.default_domain_id}) _enable_foreign_constraints(session, migrate_engine) session.execute('drop table temp_project;') def downgrade_user_table_with_copy(meta, migrate_engine, session): # For engines that don't support dropping columns, we need to do this # as a table copy. Further, in order to keep foreign key constraints # pointing at the right table, we need to be able and do a table # DROP then CREATE, rather than ALTERing the name of the table. # Fist make a copy of the user table temp_user_table = sql.Table( 'temp_user', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('password', sql.String(128)), sql.Column('enabled', sql.Boolean, default=True), sql.Column('extra', sql.Text())) temp_user_table.create(migrate_engine, checkfirst=True) user_table = sql.Table('user', meta, autoload=True) for user in session.query(user_table): session.execute('insert into temp_user (id, name, ' 'password, enabled, extra) ' 'values ( :id, :name, ' ':password, :enabled, :extra);', {'id': user.id, 'name': user.name, 'password': user.password, 'enabled': user.enabled, 'extra': user.extra}) # Now switch off constraints while we drop and then re-create the # user table, less the columns we wanted to drop _disable_foreign_constraints(session, migrate_engine) session.execute('drop table user;') # Need to create a new metadata stream since we are going to load a # different version of the user table meta2 = sql.MetaData() meta2.bind = migrate_engine user_table = sql.Table( 'user', meta2, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text()), sql.Column('password', sql.String(128)), sql.Column('enabled', sql.Boolean, default=True)) user_table.create(migrate_engine, checkfirst=True) _enable_foreign_constraints(session, migrate_engine) # Finally copy in the data from our temp table and then clean # up by deleting our temp table for user in session.query(temp_user_table): session.execute('insert into user (id, name, extra, ' 'password, enabled) ' 'values ( :id, :name, :extra, ' ':password, :enabled);', {'id': user.id, 'name': user.name, 'extra': user.extra, 'password': user.password, 'enabled': user.enabled}) session.execute('drop table temp_user;') def downgrade_project_table_with_copy(meta, migrate_engine, session): # For engines that don't support dropping columns, we need to do this # as a table copy. Further, in order to keep foreign key constraints # pointing at the right table, we need to be able and do a table # DROP then CREATE, rather than ALTERing the name of the table. # Fist make a copy of the project table temp_project_table = sql.Table( 'temp_project', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('description', sql.Text()), sql.Column('enabled', sql.Boolean, default=True), sql.Column('extra', sql.Text())) temp_project_table.create(migrate_engine, checkfirst=True) project_table = sql.Table('project', meta, autoload=True) for project in session.query(project_table): session.execute('insert into temp_project (id, name, ' 'description, enabled, extra) ' 'values ( :id, :name, ' ':description, :enabled, :extra);', {'id': project.id, 'name': project.name, 'description': project.description, 'enabled': project.enabled, 'extra': project.extra}) # Now switch off constraints while we drop and then re-create the # project table, less the columns we wanted to drop _disable_foreign_constraints(session, migrate_engine) session.execute('drop table project;') # Need to create a new metadata stream since we are going to load a # different version of the project table meta2 = sql.MetaData() meta2.bind = migrate_engine project_table = sql.Table( 'project', meta2, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text()), sql.Column('description', sql.Text()), sql.Column('enabled', sql.Boolean, default=True)) project_table.create(migrate_engine, checkfirst=True) _enable_foreign_constraints(session, migrate_engine) # Finally copy in the data from our temp table and then clean # up by deleting our temp table for project in session.query(temp_project_table): session.execute('insert into project (id, name, extra, ' 'description, enabled) ' 'values ( :id, :name, :extra, ' ':description, :enabled);', {'id': project.id, 'name': project.name, 'extra': project.extra, 'description': project.description, 'enabled': project.enabled}) session.execute("drop table temp_project;") def upgrade_user_table_with_col_create(meta, migrate_engine, session): # Create the domain_id column. We want this to be not nullable # but also a foreign key. We can't create this right off the # bat since any existing rows would cause an Integrity Error. # We therefore create it nullable, fill the column with the # default data and then set it to non nullable. sql.Table('domain', meta, autoload=True) user_table = sql.Table('user', meta, autoload=True) user_table.create_column( sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=True)) for user in session.query(user_table).all(): values = {'domain_id': CONF.identity.default_domain_id} update = user_table.update().\ where(user_table.c.id == user.id).\ values(values) migrate_engine.execute(update) # Need to commit this or setting nullable to False will fail session.commit() user_table.columns.domain_id.alter(nullable=False) # Finally, change the uniqueness settings for the name attribute session.execute('ALTER TABLE "user" DROP CONSTRAINT user_name_key;') session.execute('ALTER TABLE "user" ADD CONSTRAINT user_dom_name_unique ' 'UNIQUE (domain_id, name);') session.commit() def upgrade_project_table_with_col_create(meta, migrate_engine, session): # Create the domain_id column. We want this to be not nullable # but also a foreign key. We can't create this right off the # bat since any existing rows would cause an Integrity Error. # We therefore create it nullable, fill the column with the # default data and then set it to non nullable. sql.Table('domain', meta, autoload=True) project_table = sql.Table('project', meta, autoload=True) project_table.create_column( sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=True)) for project in session.query(project_table).all(): values = {'domain_id': CONF.identity.default_domain_id} update = project_table.update().\ where(project_table.c.id == project.id).\ values(values) migrate_engine.execute(update) # Need to commit this or setting nullable to False will fail session.commit() project_table.columns.domain_id.alter(nullable=False) # Finally, change the uniqueness settings for the name attribute session.execute('ALTER TABLE project DROP CONSTRAINT tenant_name_key;') session.execute('ALTER TABLE project ADD CONSTRAINT proj_dom_name_unique ' 'UNIQUE (domain_id, name);') def downgrade_user_table_with_col_drop(meta, migrate_engine, session): # Revert uniqueness settings for the name attribute session.execute('ALTER TABLE "user" DROP CONSTRAINT ' 'user_dom_name_unique;') # specify the constraint name so it can be referenced later session.execute('ALTER TABLE "user" ADD CONSTRAINT user_name_key ' 'UNIQUE (name);') session.commit() # And now go ahead an drop the domain_id column sql.Table('domain', meta, autoload=True) user_table = sql.Table('user', meta, autoload=True) column = sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=False) column.drop(user_table) def downgrade_project_table_with_col_drop(meta, migrate_engine, session): # Revert uniqueness settings for the name attribute session.execute('ALTER TABLE project DROP CONSTRAINT ' 'proj_dom_name_unique;') session.execute('ALTER TABLE project ADD CONSTRAINT tenant_name_key ' 'UNIQUE (name);') session.commit() # And now go ahead an drop the domain_id column sql.Table('domain', meta, autoload=True) project_table = sql.Table('project', meta, autoload=True) column = sql.Column('domain_id', sql.String(64), sql.ForeignKey('domain.id'), nullable=False) column.drop(project_table) def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine session = sessionmaker(bind=migrate_engine)() if migrate_engine.name in ['sqlite', 'mysql']: upgrade_user_table_with_copy(meta, migrate_engine, session) upgrade_project_table_with_copy(meta, migrate_engine, session) else: upgrade_user_table_with_col_create(meta, migrate_engine, session) upgrade_project_table_with_col_create(meta, migrate_engine, session) session.commit() session.close() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine session = sessionmaker(bind=migrate_engine)() if migrate_engine.name in ['sqlite', 'mysql']: downgrade_user_table_with_copy(meta, migrate_engine, session) downgrade_project_table_with_copy(meta, migrate_engine, session) else: # MySQL should in theory be able to use this path, but seems to # have problems dropping columns which are foreign keys downgrade_user_table_with_col_drop(meta, migrate_engine, session) downgrade_project_table_with_col_drop(meta, migrate_engine, session) session.commit() session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/002_sqlite_upgrade.sql0000664000175400017540000000077612323716272031206 0ustar jenkinsjenkins00000000000000CREATE TABLE token_backup ( id_hash VARCHAR(64) NOT NULL, id VARCHAR(1024), expires DATETIME, extra TEXT, PRIMARY KEY (id_hash) ); insert into token_backup select id as old_id, '', expires as old_expires, extra as old_extra from token; drop table token; CREATE TABLE token ( id_hash VARCHAR(64) NOT NULL, id VARCHAR(1024), expires DATETIME, extra TEXT, PRIMARY KEY (id_hash) ); insert into token select * from token_backup; drop table token_backup; keystone-2014.1/keystone/common/sql/migrate_repo/versions/028_fixup_group_metadata.py0000664000175400017540000001465312323716272032245 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): # The group_project_metadata table was not updated in terms of its # FK to the tenant table when the tenant->project change was made at # the 015 migration for sqlite. This upgrade fixes that. # We need to create a fake tenant table so that we can first load # the group_project_metadata at all, then do a dance of copying tables # to get us to the correct schema. meta = sql.MetaData() meta.bind = migrate_engine if migrate_engine.name != 'sqlite': return temp_tenant_table = sql.Table( 'tenant', meta, sql.Column('id', sql.String(64), primary_key=True)) temp_tenant_table.create(migrate_engine, checkfirst=True) sql.Table('user', meta, autoload=True) old_group_metadata_table = sql.Table('group_project_metadata', meta, autoload=True) # OK, we now have the table loaded, create a first # temporary table of a different name with the correct FK sql.Table('project', meta, autoload=True) temp_group_project_metadata_table = sql.Table( 'temp_group_project_metadata', meta, sql.Column( 'group_id', sql.String(64), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True), sql.Column('data', sql.Text())) temp_group_project_metadata_table.create(migrate_engine, checkfirst=True) # Populate the new temporary table, and then drop the old one session = sql.orm.sessionmaker(bind=migrate_engine)() for metadata in session.query(old_group_metadata_table): q = temp_group_project_metadata_table.insert().values( group_id=metadata.group_id, project_id=metadata.project_id, data=metadata.data) session.execute(q) session.commit() old_group_metadata_table.drop() temp_tenant_table.drop() # Now do a final table copy to get the table of the right name. # Re-init the metadata so that sqlalchemy does not get confused with # multiple versions of the same named table. meta2 = sql.MetaData() meta2.bind = migrate_engine sql.Table('project', meta2, autoload=True) new_group_project_metadata_table = sql.Table( 'group_project_metadata', meta2, sql.Column( 'group_id', sql.String(64), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True), sql.Column('data', sql.Text())) new_group_project_metadata_table.create(migrate_engine, checkfirst=True) for metadata in session.query(temp_group_project_metadata_table): q = new_group_project_metadata_table.insert().values( group_id=metadata.group_id, project_id=metadata.project_id, data=metadata.data) session.execute(q) session.commit() temp_group_project_metadata_table.drop() def downgrade(migrate_engine): # Put the group_project_metadata table back the way it was in its rather # broken state. We don't try and re-write history, since otherwise people # get out of step. meta = sql.MetaData() meta.bind = migrate_engine if migrate_engine.name != 'sqlite': return sql.Table('user', meta, autoload=True) sql.Table('project', meta, autoload=True) group_metadata_table = sql.Table('group_project_metadata', meta, autoload=True) # We want to create a temp group meta table with the FK # set to the wrong place. temp_tenant_table = sql.Table( 'tenant', meta, sql.Column('id', sql.String(64), primary_key=True)) temp_tenant_table.create(migrate_engine, checkfirst=True) temp_group_project_metadata_table = sql.Table( 'temp_group_project_metadata', meta, sql.Column( 'group_id', sql.String(64), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('tenant.id'), primary_key=True), sql.Column('data', sql.Text())) temp_group_project_metadata_table.create(migrate_engine, checkfirst=True) # Now populate the temp table and drop the real one session = sql.orm.sessionmaker(bind=migrate_engine)() for metadata in session.query(group_metadata_table): q = temp_group_project_metadata_table.insert().values( group_id=metadata.group_id, project_id=metadata.project_id, data=metadata.data) session.execute(q) session.commit() group_metadata_table.drop() # Now copy again into the correctly named table. Re-init the metadata # so that sqlalchemy does not get confused with multiple versions of the # same named table. meta2 = sql.MetaData() meta2.bind = migrate_engine sql.Table('tenant', meta2, autoload=True) new_group_project_metadata_table = sql.Table( 'group_project_metadata', meta2, sql.Column( 'group_id', sql.String(64), primary_key=True), sql.Column( 'project_id', sql.String(64), sql.ForeignKey('tenant.id'), primary_key=True), sql.Column('data', sql.Text())) new_group_project_metadata_table.create(migrate_engine, checkfirst=True) for metadata in session.query(temp_group_project_metadata_table): q = new_group_project_metadata_table.insert().values( group_id=metadata.group_id, project_id=metadata.project_id, data=metadata.data) session.execute(q) session.commit() temp_group_project_metadata_table.drop() temp_tenant_table.drop() keystone-2014.1/keystone/common/sql/migrate_repo/versions/019_fixup_role.py0000664000175400017540000000310012323716272030173 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql from keystone import config CONF = config.CONF def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine role_table = sql.Table('role', meta, autoload=True) # name should be 255 characters to match fresh database role_table.c.name.alter(type=sql.String(length=255)) # blank 'extra' field should be "{}" none = None update = role_table.update().where(role_table.c.extra == none).values( {role_table.c.extra: "{}"}) migrate_engine.execute(update) def downgrade(migrate_engine): # this fixes bugs in migration 001 and 007 that result in discrepancies # between fresh databases and databases updated from 004 (folsom). # the changes fixing 007 will be rolled back in 007's rollback if # the user desires to return to a state before the existence of the extra # column. # the name length change reflects the current default and should not be # rolled back. pass keystone-2014.1/keystone/common/sql/migrate_repo/versions/030_drop_credential_constraint_sqlite.py0000664000175400017540000001131712323716272035004 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy from sqlalchemy.orm import sessionmaker def upgrade(migrate_engine): if migrate_engine.name == 'sqlite': drop_credential_table_foreign_key_constraints_for_sqlite( migrate_engine) def downgrade(migrate_engine): if migrate_engine.name == 'sqlite': add_credential_table_foreign_key_constraints_for_sqlite(migrate_engine) def drop_credential_table_foreign_key_constraints_for_sqlite(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine # NOTE(nachiappan): SQLite does not support ALTER TABLE DROP constraint. # So we need to move the data to new credenital table # created without constraints, drop the old table and # rename the new table to credential. sqlalchemy.Table('user', meta, autoload=True) tenant_table = sqlalchemy.Table( 'tenant', meta, sqlalchemy.Column('id', sqlalchemy.String(64), primary_key=True), sqlalchemy.Column( 'name', sqlalchemy.String(64), unique=True, nullable=False), sqlalchemy.Column('extra', sqlalchemy.Text())) tenant_table.create(migrate_engine, checkfirst=True) cred_table = sqlalchemy.Table('credential', meta, autoload=True) session = sessionmaker(bind=migrate_engine)() new_credential_table = sqlalchemy.Table( 'new_credential', meta, sqlalchemy.Column('id', sqlalchemy.String(64), primary_key=True), sqlalchemy.Column('user_id', sqlalchemy.String(64), nullable=False), sqlalchemy.Column('project_id', sqlalchemy.String(64)), sqlalchemy.Column('blob', sqlalchemy.Text(), nullable=False), sqlalchemy.Column('type', sqlalchemy.String(255), nullable=False), sqlalchemy.Column('extra', sqlalchemy.Text())) new_credential_table.create(migrate_engine, checkfirst=True) insert = new_credential_table.insert() for credential in session.query(cred_table): insert.execute({'id': credential.id, 'user_id': credential.user_id, 'project_id': credential.project_id, 'blob': credential.blob, 'type': credential.type, 'extra': credential.extra}) cred_table.drop() tenant_table.drop() new_credential_table.rename('credential') session.commit() session.close() def add_credential_table_foreign_key_constraints_for_sqlite(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine cred_table = sqlalchemy.Table('credential', meta, autoload=True) sqlalchemy.Table('user', meta, autoload=True) session = sessionmaker(bind=migrate_engine)() old_credential_table = sqlalchemy.Table( 'old_credential', meta, sqlalchemy.Column('id', sqlalchemy.String(64), primary_key=True), sqlalchemy.Column('user_id', sqlalchemy.String(64), sqlalchemy.ForeignKey('user.id'), nullable=False), # NOTE(nachiappan): Not creating the foreign key constraint with # project table as version 15 conflicts with # version 7. sqlalchemy.Column('project_id', sqlalchemy.String(64)), sqlalchemy.Column('blob', sqlalchemy.Text(), nullable=False), sqlalchemy.Column('type', sqlalchemy.String(255), nullable=False), sqlalchemy.Column('extra', sqlalchemy.Text())) old_credential_table.create(migrate_engine, checkfirst=True) insert = old_credential_table.insert() for credential in session.query(cred_table): insert.execute({'id': credential.id, 'user_id': credential.user_id, 'project_id': credential.project_id, 'blob': credential.blob, 'type': credential.type, 'extra': credential.extra}) cred_table.drop() old_credential_table.rename('credential') session.commit() session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/042_endpoint_enabled.py0000664000175400017540000001245512323716267031326 0ustar jenkinsjenkins00000000000000# Copyright 2014 IBM Corp. # # 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. """Adds an `enabled` column to the `endpoint` table. The enabled value for the `endpoint` table was stored in the `extra` column as part of a JSON string. To upgrade, the `enabled` column is added with a default value of ``true``, then we check all the `extra` JSON for disabled and set the value to ``false`` for those. Downgrade is essentially the opposite -- we update the JSON with ``"enabled": false`` for any endpoints that are disabled and drop the `enabled` column. """ import sqlalchemy as sql from sqlalchemy.orm import sessionmaker from keystone.openstack.common import jsonutils from keystone.openstack.common import strutils def _migrate_enabled_from_extra(migrate_engine, endpoint_table): """Remove `enabled` from `extra`, put it in the `enabled` column.""" eps = list(endpoint_table.select().execute()) for ep in eps: extra_dict = jsonutils.loads(ep.extra) if 'enabled' not in extra_dict: # `enabled` and `extra` are already as expected. continue enabled = extra_dict.pop('enabled') if enabled is None: enabled = True else: enabled = strutils.bool_from_string(enabled, default=True) new_values = { 'enabled': enabled, 'extra': jsonutils.dumps(extra_dict), } f = endpoint_table.c.id == ep.id update = endpoint_table.update().where(f).values(new_values) migrate_engine.execute(update) def _migrate_enabled_to_extra(migrate_engine, endpoint_table): """Get enabled value from 'enabled' column and put it in 'extra' JSON. Only put the enabled value to the 'extra' JSON if it's False, since the default is True. """ eps = list(endpoint_table.select().execute()) for ep in eps: if ep.enabled: # Nothing to do since the endpoint is enabled. continue extra_dict = jsonutils.loads(ep.extra) extra_dict['enabled'] = False new_values = { 'extra': jsonutils.dumps(extra_dict), } f = endpoint_table.c.id == ep.id update = endpoint_table.update().where(f).values(new_values) migrate_engine.execute(update) def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine endpoint_table = sql.Table('endpoint', meta, autoload=True) enabled_column = sql.Column('enabled', sql.Boolean, nullable=False, default=True, server_default='1') enabled_column.create(endpoint_table) _migrate_enabled_from_extra(migrate_engine, endpoint_table) def _downgrade_endpoint_table_with_copy(meta, migrate_engine): # Used with databases that don't support dropping a column (e.g., sqlite). maker = sessionmaker(bind=migrate_engine) session = maker() session.execute('ALTER TABLE endpoint RENAME TO orig_endpoint;') # Need to load the metadata for the service table since it's used as # foreign key. sql.Table('service', meta, autoload=True) endpoint_table = sql.Table( 'endpoint', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('legacy_endpoint_id', sql.String(64)), sql.Column('interface', sql.String(8), nullable=False), sql.Column('region', sql.String(255)), sql.Column('service_id', sql.String(64), sql.ForeignKey('service.id'), nullable=False), sql.Column('url', sql.Text(), nullable=False), sql.Column('extra', sql.Text())) endpoint_table.create(migrate_engine, checkfirst=True) orig_endpoint_table = sql.Table('orig_endpoint', meta, autoload=True) for endpoint in session.query(orig_endpoint_table): new_values = { 'id': endpoint.id, 'legacy_endpoint_id': endpoint.legacy_endpoint_id, 'interface': endpoint.interface, 'region': endpoint.region, 'service_id': endpoint.service_id, 'url': endpoint.url, 'extra': endpoint.extra, } session.execute('insert into endpoint (id, legacy_endpoint_id, ' 'interface, region, service_id, url, extra) ' 'values ( :id, :legacy_endpoint_id, :interface, ' ':region, :service_id, :url, :extra);', new_values) session.execute('drop table orig_endpoint;') session.close() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine endpoint_table = sql.Table('endpoint', meta, autoload=True) _migrate_enabled_to_extra(migrate_engine, endpoint_table) if migrate_engine.name == 'sqlite': meta.clear() _downgrade_endpoint_table_with_copy(meta, migrate_engine) return endpoint_table.c.enabled.drop() keystone-2014.1/keystone/common/sql/migrate_repo/versions/006_add_policy_table.py0000664000175400017540000000233312323716272031300 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine policy_table = sql.Table( 'policy', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('type', sql.String(255), nullable=False), sql.Column('blob', sql.Text(), nullable=False), sql.Column('extra', sql.Text())) policy_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine policy_table = sql.Table('policy', meta, autoload=True) policy_table.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/common/sql/migrate_repo/versions/008_create_default_domain.py0000664000175400017540000000317712323716272032331 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import json import sqlalchemy as sql from sqlalchemy import orm from keystone import config CONF = config.CONF def upgrade(migrate_engine): """Creates the default domain.""" meta = sql.MetaData() meta.bind = migrate_engine domain_table = sql.Table('domain', meta, autoload=True) domain = { 'id': CONF.identity.default_domain_id, 'name': 'Default', 'enabled': True, 'extra': json.dumps({ 'description': 'Owns users and tenants (i.e. projects) available ' 'on Identity API v2.'})} session = orm.sessionmaker(bind=migrate_engine)() insert = domain_table.insert() insert.execute(domain) session.commit() def downgrade(migrate_engine): """Delete the default domain.""" meta = sql.MetaData() meta.bind = migrate_engine sql.Table('domain', meta, autoload=True) session = orm.sessionmaker(bind=migrate_engine)() session.execute( 'DELETE FROM domain WHERE id=:id', {'id': CONF.identity.default_domain_id}) session.commit() keystone-2014.1/keystone/common/sql/migrate_repo/versions/017_membership_role.py0000664000175400017540000000760712323716272031211 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json import sqlalchemy as sql from keystone import config CONF = config.CONF def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine sql.Table('user', meta, autoload=True) sql.Table('project', meta, autoload=True) role_table = sql.Table('role', meta, autoload=True) user_project_role_table = sql.Table( 'user_project_metadata', meta, sql.Column('user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column('project_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True), sql.Column('data', sql.Text())) user_project_role_table.create(migrate_engine, checkfirst=True) conn = migrate_engine.connect() conn.execute(role_table.insert(), id=CONF.member_role_id, name=CONF.member_role_name, extra=json.dumps({'description': 'Default role for project membership', 'enabled': 'True'})) user_project_membership_table = sql.Table('user_project_membership', meta, autoload=True) session = sql.orm.sessionmaker(bind=migrate_engine)() for membership in session.query(user_project_membership_table): data = {'roles': [config.CONF.member_role_id]} ins = user_project_role_table.insert().values( user_id=membership.user_id, project_id=membership.tenant_id, data=json.dumps(data)) conn.execute(ins) session.close() user_project_membership_table.drop() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine sql.Table('user', meta, autoload=True) sql.Table('project', meta, autoload=True) user_project_membership_table = sql.Table( 'user_project_membership', meta, sql.Column( 'user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column( 'tenant_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True)) user_project_membership_table.create(migrate_engine, checkfirst=True) user_project_metadata_table = sql.Table( 'user_project_metadata', meta, autoload=True) session = sql.orm.sessionmaker(bind=migrate_engine)() for membership in session.query(user_project_metadata_table): if 'roles' in membership: roles = membership['roles'] if config.CONF.member_role_id in roles: user_project_membership_table.insert().values( user_id=membership.user_id, tenant_id=membership.project_id) session.close() role_table = sql.Table('role', meta, autoload=True) conn = migrate_engine.connect() user_project_membership_table = sql.Table( 'user_project_membership', meta, autoload=True) role_table = sql.Table('role', meta, autoload=True) conn.execute(role_table.delete().where(role_table.c.id == config.CONF.member_role_id)) user_project_metadata_table.drop() keystone-2014.1/keystone/common/sql/migrate_repo/versions/009_normalize_identity.py0000664000175400017540000001010312323716272031730 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from sqlalchemy import Column, MetaData, String, Table, Text, types from sqlalchemy.orm import sessionmaker #sqlite doesn't support dropping columns. Copy to a new table instead def downgrade_user_table_with_copy(meta, migrate_engine): maker = sessionmaker(bind=migrate_engine) session = maker() session.execute("ALTER TABLE user RENAME TO orig_user;") user_table = Table( 'user', meta, Column('id', String(64), primary_key=True), Column('name', String(64), unique=True, nullable=False), Column('extra', Text())) user_table.create(migrate_engine, checkfirst=True) orig_user_table = Table('orig_user', meta, autoload=True) for user in session.query(orig_user_table): session.execute("insert into user (id, name, extra) " "values ( :id, :name, :extra);", {'id': user.id, 'name': user.name, 'extra': user.extra}) session.execute("drop table orig_user;") session.close() def downgrade_tenant_table_with_copy(meta, migrate_engine): maker = sessionmaker(bind=migrate_engine) session = maker() session.execute("ALTER TABLE tenant RENAME TO orig_tenant;") tenant_table = Table( 'tenant', meta, Column('id', String(64), primary_key=True), Column('name', String(64), unique=True, nullable=False), Column('extra', Text())) tenant_table.create(migrate_engine, checkfirst=True) orig_tenant_table = Table('orig_tenant', meta, autoload=True) for tenant in session.query(orig_tenant_table): session.execute("insert into tenant (id, name, extra) " "values ( :id, :name, :extra);", {'id': tenant.id, 'name': tenant.name, 'extra': tenant.extra}) session.execute("drop table orig_tenant;") session.close() def downgrade_user_table_with_column_drop(meta, migrate_engine): user_table = Table('user', meta, autoload=True) user_table.drop_column(Column('password', String(128))) user_table.drop_column(Column('enabled', types.Boolean, default=True)) def downgrade_tenant_table_with_column_drop(meta, migrate_engine): tenant_table = Table('tenant', meta, autoload=True) tenant_table.drop_column(Column('description', Text())) tenant_table.drop_column(Column('enabled', types.Boolean)) def upgrade_user_table(meta, migrate_engine): user_table = Table('user', meta, autoload=True) user_table.create_column(Column('password', String(128))) user_table.create_column(Column('enabled', types.Boolean, default=True)) def upgrade_tenant_table(meta, migrate_engine): tenant_table = Table('tenant', meta, autoload=True) tenant_table.create_column(Column('description', Text())) tenant_table.create_column(Column('enabled', types.Boolean)) def upgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine upgrade_user_table(meta, migrate_engine) upgrade_tenant_table(meta, migrate_engine) def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine if migrate_engine.name == 'sqlite': downgrade_user_table_with_copy(meta, migrate_engine) downgrade_tenant_table_with_copy(meta, migrate_engine) else: downgrade_user_table_with_column_drop(meta, migrate_engine) downgrade_tenant_table_with_column_drop(meta, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/027_set_engine_mysql_innodb.py0000664000175400017540000001402112323716272032720 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql from sqlalchemy import MetaData from keystone.common.sql import migration_helpers def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; # bind migrate_engine to your metadata if migrate_engine.name != 'mysql': # InnoDB / MyISAM only applies to MySQL. return # This is a list of all the tables that might have been created with MyISAM # rather than InnoDB. tables = [ 'credential', 'domain', 'ec2_credential', 'endpoint', 'group', 'group_domain_metadata', 'group_project_metadata', 'policy', 'project', 'role', 'service', 'token', 'trust', 'trust_role', 'user', 'user_domain_metadata', 'user_group_membership', 'user_project_metadata', ] meta = MetaData() meta.bind = migrate_engine domain_table = sql.Table('domain', meta, autoload=True) endpoint_table = sql.Table('endpoint', meta, autoload=True) group_table = sql.Table('group', meta, autoload=True) group_domain_metadata_table = sql.Table('group_domain_metadata', meta, autoload=True) group_project_metadata_table = sql.Table('group_project_metadata', meta, autoload=True) project_table = sql.Table('project', meta, autoload=True) service_table = sql.Table('service', meta, autoload=True) user_table = sql.Table('user', meta, autoload=True) user_domain_metadata_table = sql.Table('user_domain_metadata', meta, autoload=True) user_group_membership_table = sql.Table('user_group_membership', meta, autoload=True) # Mapping of table name to the constraints on that table, # so we can create them. table_constraints = { 'endpoint': [{'table': endpoint_table, 'fk_column': 'service_id', 'ref_column': service_table.c.id}, ], 'group': [{'table': group_table, 'fk_column': 'domain_id', 'ref_column': domain_table.c.id}, ], 'group_domain_metadata': [{'table': group_domain_metadata_table, 'fk_column': 'domain_id', 'ref_column': domain_table.c.id}, ], 'group_project_metadata': [{'table': group_project_metadata_table, 'fk_column': 'project_id', 'ref_column': project_table.c.id}, ], 'project': [{'table': project_table, 'fk_column': 'domain_id', 'ref_column': domain_table.c.id}, ], 'user': [{'table': user_table, 'fk_column': 'domain_id', 'ref_column': domain_table.c.id}, ], 'user_domain_metadata': [{'table': user_domain_metadata_table, 'fk_column': 'domain_id', 'ref_column': domain_table.c.id}, ], 'user_group_membership': [{'table': user_group_membership_table, 'fk_column': 'user_id', 'ref_column': user_table.c.id}, {'table': user_group_membership_table, 'fk_column': 'group_id', 'ref_column': group_table.c.id}, ], 'user_project_metadata': [{'table': group_project_metadata_table, 'fk_column': 'project_id', 'ref_column': project_table.c.id}, ], } # Maps a table name to the tables that reference it as a FK constraint # (See the map above). ref_tables_map = { 'service': ['endpoint', ], 'domain': ['group', 'group_domain_metadata', 'project', 'user', 'user_domain_metadata', ], 'project': ['group_project_metadata', 'user_project_metadata', ], 'user': ['user_group_membership', ], 'group': ['user_group_membership', ], } # The names of tables that need to have their FKs added. fk_table_names = set() d = migrate_engine.execute("SHOW TABLE STATUS WHERE Engine!='InnoDB';") for row in d.fetchall(): table_name = row[0] if table_name not in tables: # Skip this table since it's not a Keystone table. continue migrate_engine.execute("ALTER TABLE `%s` Engine=InnoDB" % table_name) # Will add the FKs to the table if any of # a) the table itself was converted # b) the tables that the table referenced were converted if table_name in table_constraints: fk_table_names.add(table_name) ref_tables = ref_tables_map.get(table_name, []) for other_table_name in ref_tables: fk_table_names.add(other_table_name) # Now add all the FK constraints to those tables for table_name in fk_table_names: constraints = table_constraints.get(table_name) migration_helpers.add_constraints(constraints) def downgrade(migrate_engine): pass keystone-2014.1/keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py0000664000175400017540000001663012323716272031550 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql from sqlalchemy.orm import sessionmaker from keystone.common.sql import migration_helpers def rename_with_constraints(meta, legacy_project_table_name, new_project_table_name, legacy_user_project_membership_table_name, new_user_project_membership_table_name): # Not all RDBMSs support renaming a table that has foreign key constraints # on it, so drop FK constraints before renaming and then replace FKs # afterwards. credential_table = sql.Table('credential', meta, autoload=True) group_project_meta_table = sql.Table('group_project_metadata', meta, autoload=True) project_table = sql.Table(legacy_project_table_name, meta, autoload=True) user_project_membership_table = sql.Table( legacy_user_project_membership_table_name, meta, autoload=True) user_table = sql.Table('user', meta, autoload=True) constraints = [{'table': credential_table, 'fk_column': 'project_id', 'ref_column': project_table.c.id}, {'table': group_project_meta_table, 'fk_column': 'project_id', 'ref_column': project_table.c.id}, {'table': user_project_membership_table, 'fk_column': 'tenant_id', 'ref_column': project_table.c.id}, {'table': user_project_membership_table, 'fk_column': 'user_id', 'ref_column': user_table.c.id}] renames = { new_project_table_name: project_table, new_user_project_membership_table_name: user_project_membership_table} migration_helpers.rename_tables_with_constraints(renames, constraints, meta.bind) def upgrade_with_rename(meta, migrate_engine): legacy_project_table_name = 'tenant' new_project_table_name = 'project' legacy_user_project_membership_table_name = 'user_tenant_membership' new_user_project_membership_table_name = 'user_project_membership' rename_with_constraints(meta, legacy_project_table_name, new_project_table_name, legacy_user_project_membership_table_name, new_user_project_membership_table_name) def downgrade_with_rename(meta, migrate_engine): legacy_project_table_name = 'project' new_project_table_name = 'tenant' legacy_user_project_membership_table_name = 'user_project_membership' new_user_project_membership_table_name = 'user_tenant_membership' rename_with_constraints(meta, legacy_project_table_name, new_project_table_name, legacy_user_project_membership_table_name, new_user_project_membership_table_name) def upgrade_with_copy(meta, migrate_engine): sql.Table('user', meta, autoload=True) project_table = sql.Table( 'project', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text()), sql.Column('description', sql.Text(), nullable=True), sql.Column('enabled', sql.types.Boolean, default=True)) project_table.create(migrate_engine, checkfirst=True) user_project_membership_table = sql.Table( 'user_project_membership', meta, sql.Column( 'user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column( 'tenant_id', sql.String(64), sql.ForeignKey('project.id'), primary_key=True)) user_project_membership_table.create(migrate_engine, checkfirst=True) session = sessionmaker(bind=migrate_engine)() tenant_table = sql.Table('tenant', meta, autoload=True) insert = project_table.insert() for tenant in session.query(tenant_table): insert.execute({'id': tenant.id, 'name': tenant.name, 'extra': tenant.extra, 'description': tenant.description, 'enabled': tenant.enabled}) user_tenant_membership_table = sql.Table('user_tenant_membership', meta, autoload=True) insert = user_project_membership_table.insert() for user_id, tenant_id in session.query(user_tenant_membership_table): insert.execute({'user_id': user_id, 'tenant_id': tenant_id}) session.commit() session.close() user_tenant_membership_table.drop() tenant_table.drop() def downgrade_with_copy(meta, migrate_engine): sql.Table('user', meta, autoload=True) tenant_table = sql.Table( 'tenant', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text()), sql.Column('description', sql.Text(), nullable=True), sql.Column('enabled', sql.types.Boolean)) tenant_table.create(migrate_engine, checkfirst=True) user_tenant_membership_table = sql.Table( 'user_tenant_membership', meta, sql.Column( 'user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column( 'tenant_id', sql.String(64), sql.ForeignKey('tenant.id'), primary_key=True)) user_tenant_membership_table.create(migrate_engine, checkfirst=True) session = sessionmaker(bind=migrate_engine)() project_table = sql.Table('project', meta, autoload=True) insert = tenant_table.insert() for project in session.query(project_table): insert.values(project).execute() project_table.drop() user_project_membership_table = sql.Table('user_project_membership', meta, autoload=True) insert = user_tenant_membership_table.insert() for membership in session.query(user_project_membership_table): insert.execute(membership) user_project_membership_table.drop() session.commit() session.close() def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine if migrate_engine.name == "sqlite": upgrade_with_copy(meta, migrate_engine) else: upgrade_with_rename(meta, migrate_engine) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine if migrate_engine.name == "sqlite": downgrade_with_copy(meta, migrate_engine) else: downgrade_with_rename(meta, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/002_token_id_hash.py0000664000175400017540000000267312323716272030624 0ustar jenkinsjenkins00000000000000# Copyright (c) 2012 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 sqlalchemy import Column, MetaData, String, Table def upgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine token = Table('token', meta, autoload=True) old_id_col = token.c.id old_id_col.alter(name='id_hash') # Note: We obtain a new metadata reference to avoid # sqlalchemy.exc.ArgumentError: # Trying to redefine primary-key column 'id' as a non-primary-key... meta = MetaData() meta.bind = migrate_engine token = Table('token', meta, autoload=True) new_id = Column("id", String(2048)) token.create_column(new_id) def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine token = Table('token', meta, autoload=True) token.drop_column('id') token = Table('token', meta, autoload=True) id_col = token.c.id_hash id_col.alter(name='id') keystone-2014.1/keystone/common/sql/migrate_repo/versions/002_sqlite_downgrade.sql0000664000175400017540000000020312323716272031512 0ustar jenkinsjenkins00000000000000drop table token; CREATE TABLE token ( id VARCHAR(64) NOT NULL, expires DATETIME, extra TEXT, PRIMARY KEY (id) ); keystone-2014.1/keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py0000664000175400017540000000507112323716272030433 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql from keystone.common.sql import migration_helpers def upgrade(migrate_engine): """Create API-version specific endpoint tables.""" meta = sql.MetaData() meta.bind = migrate_engine legacy_table = sql.Table('endpoint', meta, autoload=True) renames = {'endpoint_v2': legacy_table} service_table = sql.Table('service', meta, autoload=True) constraints = [{'table': legacy_table, 'fk_column': 'service_id', 'ref_column': service_table.c.id}] migration_helpers.rename_tables_with_constraints(renames, constraints, migrate_engine) sql.Table('service', meta, autoload=True) new_table = sql.Table( 'endpoint_v3', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('legacy_endpoint_id', sql.String(64)), sql.Column('interface', sql.String(8), nullable=False), sql.Column('region', sql.String(255)), sql.Column('service_id', sql.String(64), sql.ForeignKey('service.id'), nullable=False), sql.Column('url', sql.Text(), nullable=False), sql.Column('extra', sql.Text())) new_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): """Replace API-version specific endpoint tables with one based on v2.""" meta = sql.MetaData() meta.bind = migrate_engine new_table = sql.Table('endpoint_v3', meta, autoload=True) new_table.drop() legacy_table = sql.Table('endpoint_v2', meta, autoload=True) renames = {'endpoint': legacy_table} service_table = sql.Table('service', meta, autoload=True) constraints = [{'table': legacy_table, 'fk_column': 'service_id', 'ref_column': service_table.c.id}] migration_helpers.rename_tables_with_constraints(renames, constraints, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py0000664000175400017540000001320612323716272031611 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine # catalog service_table = sql.Table( 'service', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('type', sql.String(255)), sql.Column('extra', sql.Text())) service_table.create(migrate_engine, checkfirst=True) endpoint_table = sql.Table( 'endpoint', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('region', sql.String(255)), sql.Column('service_id', sql.String(64), sql.ForeignKey('service.id'), nullable=False), sql.Column('extra', sql.Text())) endpoint_table.create(migrate_engine, checkfirst=True) # identity role_table = sql.Table( 'role', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(255), unique=True, nullable=False)) role_table.create(migrate_engine, checkfirst=True) if migrate_engine.name == 'ibm_db_sa': # NOTE(blk-u): SQLAlchemy for PostgreSQL picks the name tenant_name_key # for the unique constraint, but for DB2 doesn't give the UC a name # unless we tell it to and there is no DDL to alter a column to drop # an unnamed unique constraint, so this code creates a named unique # constraint on the name column rather than an unnamed one. # (This is used in migration 16.) tenant_table = sql.Table( 'tenant', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), nullable=False), sql.Column('extra', sql.Text()), sql.UniqueConstraint('name', name='tenant_name_key')) else: tenant_table = sql.Table( 'tenant', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text())) tenant_table.create(migrate_engine, checkfirst=True) metadata_table = sql.Table( 'metadata', meta, sql.Column('user_id', sql.String(64), primary_key=True), sql.Column('tenant_id', sql.String(64), primary_key=True), sql.Column('data', sql.Text())) metadata_table.create(migrate_engine, checkfirst=True) ec2_credential_table = sql.Table( 'ec2_credential', meta, sql.Column('access', sql.String(64), primary_key=True), sql.Column('secret', sql.String(64)), sql.Column('user_id', sql.String(64)), sql.Column('tenant_id', sql.String(64))) ec2_credential_table.create(migrate_engine, checkfirst=True) if migrate_engine.name == 'ibm_db_sa': # NOTE(blk-u): SQLAlchemy for PostgreSQL picks the name user_name_key # for the unique constraint, but for DB2 doesn't give the UC a name # unless we tell it to and there is no DDL to alter a column to drop # an unnamed unique constraint, so this code creates a named unique # constraint on the name column rather than an unnamed one. # (This is used in migration 16.) user_table = sql.Table( 'user', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), nullable=False), sql.Column('extra', sql.Text()), sql.UniqueConstraint('name', name='user_name_key')) else: user_table = sql.Table( 'user', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('name', sql.String(64), unique=True, nullable=False), sql.Column('extra', sql.Text())) user_table.create(migrate_engine, checkfirst=True) user_tenant_membership_table = sql.Table( 'user_tenant_membership', meta, sql.Column( 'user_id', sql.String(64), sql.ForeignKey('user.id'), primary_key=True), sql.Column( 'tenant_id', sql.String(64), sql.ForeignKey('tenant.id'), primary_key=True)) user_tenant_membership_table.create(migrate_engine, checkfirst=True) # token token_table = sql.Table( 'token', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('expires', sql.DateTime()), sql.Column('extra', sql.Text())) token_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): # Operations to reverse the above upgrade go here. meta = sql.MetaData() meta.bind = migrate_engine tables = ['user_tenant_membership', 'token', 'user', 'tenant', 'role', 'metadata', 'ec2_credential', 'endpoint', 'service'] for t in tables: table = sql.Table(t, meta, autoload=True) table.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/common/sql/migrate_repo/versions/035_add_compound_revoked_token_index.py0000664000175400017540000000220512323716272034564 0ustar jenkinsjenkins00000000000000# Copyright 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_expires_valid', token.c.expires, token.c.valid) idx.create(migrate_engine) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_expires_valid', token.c.expires, token.c.valid) idx.drop(migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/039_grant_to_assignment.py0000664000175400017540000002255412323716267032110 0ustar jenkinsjenkins00000000000000# Copyright 2014 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import json import sqlalchemy as sql from keystone.assignment.backends import sql as assignment_sql USER_PROJECT_TABLE = 'user_project_metadata' GROUP_PROJECT_TABLE = 'group_project_metadata' USER_DOMAIN_TABLE = 'user_domain_metadata' GROUP_DOMAIN_TABLE = 'group_domain_metadata' ASSIGNMENT_TABLE = 'assignment' GRANT_TABLES = [USER_PROJECT_TABLE, USER_DOMAIN_TABLE, GROUP_PROJECT_TABLE, GROUP_DOMAIN_TABLE] def migrate_grant_table(meta, migrate_engine, session, table_name): def extract_actor_and_target(table_name, composite_grant): if table_name == USER_PROJECT_TABLE: return {'type': assignment_sql.AssignmentType.USER_PROJECT, 'actor_id': composite_grant.user_id, 'target_id': composite_grant.project_id} elif table_name == GROUP_PROJECT_TABLE: return {'type': assignment_sql.AssignmentType.GROUP_PROJECT, 'actor_id': composite_grant.group_id, 'target_id': composite_grant.project_id} elif table_name == USER_DOMAIN_TABLE: return {'type': assignment_sql.AssignmentType.USER_DOMAIN, 'actor_id': composite_grant.user_id, 'target_id': composite_grant.domain_id} else: return {'type': assignment_sql.AssignmentType.GROUP_DOMAIN, 'actor_id': composite_grant.group_id, 'target_id': composite_grant.domain_id} def grant_to_grant_dict_list(table_name, composite_grant): """Make each role in the list of this entry a separate assignment.""" json_metadata = json.loads(composite_grant.data) role_dict_list = [] if 'roles' in json_metadata: for x in json_metadata['roles']: if x.get('id') is None: # Looks like an invalid role, drop it break grant = extract_actor_and_target(table_name, composite_grant) grant['role_id'] = x.get('id') grant['inherited'] = False if x.get('inherited_to') == 'projects': grant['inherited'] = True role_dict_list.append(grant) return role_dict_list upgrade_table = sql.Table(table_name, meta, autoload=True) assignment_table = sql.Table(ASSIGNMENT_TABLE, meta, autoload=True) # For each grant in this table, expand it out to be an assignment entry for # each role in the metadata for grant in session.query(upgrade_table).all(): for grant_role in grant_to_grant_dict_list(table_name, grant): new_entry = assignment_table.insert().values( type=grant_role['type'], actor_id=grant_role['actor_id'], target_id=grant_role['target_id'], role_id=grant_role['role_id'], inherited=grant_role['inherited']) migrate_engine.execute(new_entry) # Delete all the rows migrate_engine.execute(upgrade_table.delete()) def downgrade_assignment_table(meta, migrate_engine): def add_to_dict_list(metadata, assignment_row): """Update a metadata dict list with the role. For the assignment row supplied, we need to append the role_id into the metadata list of dicts. If the row is inherited, then we mark it so in the dict we append. """ new_entry = {'id': assignment_row.role_id} if assignment_row.inherited and ( assignment_row.type == assignment_sql.AssignmentType.USER_DOMAIN or assignment_row.type == assignment_sql.AssignmentType.GROUP_DOMAIN): new_entry['inherited_to'] = 'projects' if metadata is not None: json_metadata = json.loads(metadata) else: json_metadata = {} if json_metadata.get('roles') is None: json_metadata['roles'] = [] json_metadata['roles'].append(new_entry) return json.dumps(json_metadata) def build_user_project_entry(meta, session, row): update_table = sql.Table(USER_PROJECT_TABLE, meta, autoload=True) q = session.query(update_table) q = q.filter_by(user_id=row.actor_id) q = q.filter_by(project_id=row.target_id) ref = q.first() if ref is not None: values = {'data': add_to_dict_list(ref.data, row)} update = update_table.update().where( update_table.c.user_id == ref.user_id).where( update_table.c.project_id == ref.project_id).values(values) else: values = {'user_id': row.actor_id, 'project_id': row.target_id, 'data': add_to_dict_list(None, row)} update = update_table.insert().values(values) return update def build_group_project_entry(meta, session, row): update_table = sql.Table(GROUP_PROJECT_TABLE, meta, autoload=True) q = session.query(update_table) q = q.filter_by(group_id=row.actor_id) q = q.filter_by(project_id=row.target_id) ref = q.first() if ref is not None: values = {'data': add_to_dict_list(ref.data, row)} update = update_table.update().where( update_table.c.group_id == ref.group_id).where( update_table.c.project_id == ref.project_id).values(values) else: values = {'group_id': row.actor_id, 'project_id': row.target_id, 'data': add_to_dict_list(None, row)} update = update_table.insert().values(values) return update def build_user_domain_entry(meta, session, row): update_table = sql.Table(USER_DOMAIN_TABLE, meta, autoload=True) q = session.query(update_table) q = q.filter_by(user_id=row.actor_id) q = q.filter_by(domain_id=row.target_id) ref = q.first() if ref is not None: values = {'data': add_to_dict_list(ref.data, row)} update = update_table.update().where( update_table.c.user_id == ref.user_id).where( update_table.c.domain_id == ref.domain_id).values(values) else: values = {'user_id': row.actor_id, 'domain_id': row.target_id, 'data': add_to_dict_list(None, row)} update = update_table.insert().values(values) return update def build_group_domain_entry(meta, session, row): update_table = sql.Table(GROUP_DOMAIN_TABLE, meta, autoload=True) q = session.query(update_table) q = q.filter_by(group_id=row.actor_id) q = q.filter_by(domain_id=row.target_id) ref = q.first() if ref is not None: values = {'data': add_to_dict_list(ref.data, row)} update = update_table.update().where( update_table.c.group_id == ref.group_id).where( update_table.c.domain_id == ref.domain_id).values(values) else: values = {'group_id': row.actor_id, 'domain_id': row.target_id, 'data': add_to_dict_list(None, row)} update = update_table.insert().values(values) return update def build_update(meta, session, row): """Build an update or an insert to the correct metadata table.""" if row.type == assignment_sql.AssignmentType.USER_PROJECT: return build_user_project_entry(meta, session, row) elif row.type == assignment_sql.AssignmentType.GROUP_PROJECT: return build_group_project_entry(meta, session, row) elif row.type == assignment_sql.AssignmentType.USER_DOMAIN: return build_user_domain_entry(meta, session, row) elif row.type == assignment_sql.AssignmentType.GROUP_DOMAIN: return build_group_domain_entry(meta, session, row) # If the row type doesn't match any that we understand we drop # the data. session = sql.orm.sessionmaker(bind=migrate_engine)() downgrade_table = sql.Table(ASSIGNMENT_TABLE, meta, autoload=True) for assignment in session.query(downgrade_table).all(): update = build_update(meta, session, assignment) if update is not None: migrate_engine.execute(update) session.commit() # Delete all the rows migrate_engine.execute(downgrade_table.delete()) session.commit() session.close() def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine session = sql.orm.sessionmaker(bind=migrate_engine)() for table_name in GRANT_TABLES: migrate_grant_table(meta, migrate_engine, session, table_name) session.commit() session.close() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine downgrade_assignment_table(meta, migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/026_drop_user_group_constraints.py0000664000175400017540000000472612323716272033701 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy from keystone.common.sql import migration_helpers def list_constraints(migrate_engine): meta = sqlalchemy.MetaData() meta.bind = migrate_engine user_table = sqlalchemy.Table('user', meta, autoload=True) sqlalchemy.Table('project', meta, autoload=True) group_table = sqlalchemy.Table('group', meta, autoload=True) user_domain_metadata_table = sqlalchemy.Table('user_domain_metadata', meta, autoload=True) group_domain_metadata_table = sqlalchemy.Table('group_domain_metadata', meta, autoload=True) user_project_metadata_table = sqlalchemy.Table('user_project_metadata', meta, autoload=True) group_project_metadata_table = sqlalchemy.Table('group_project_metadata', meta, autoload=True) constraints = [{'table': user_domain_metadata_table, 'fk_column': 'user_id', 'ref_column': user_table.c.id}, {'table': group_domain_metadata_table, 'fk_column': 'group_id', 'ref_column': group_table.c.id}, {'table': user_project_metadata_table, 'fk_column': 'user_id', 'ref_column': user_table.c.id}, {'table': group_project_metadata_table, 'fk_column': 'group_id', 'ref_column': group_table.c.id}, ] return constraints def upgrade(migrate_engine): if migrate_engine.name == 'sqlite': return migration_helpers.remove_constraints(list_constraints(migrate_engine)) def downgrade(migrate_engine): if migrate_engine.name == 'sqlite': return migration_helpers.add_constraints(list_constraints(migrate_engine)) keystone-2014.1/keystone/common/sql/migrate_repo/versions/025_add_index_to_valid.py0000664000175400017540000000207612323716272031627 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_valid', token.c.valid) idx.create(migrate_engine) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine token = sql.Table('token', meta, autoload=True) idx = sql.Index('ix_token_valid', token.c.valid) idx.drop(migrate_engine) keystone-2014.1/keystone/common/sql/migrate_repo/versions/022_move_legacy_endpoint_id.py0000664000175400017540000000440012323716272032663 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json import sqlalchemy as sql from sqlalchemy import orm from keystone import config CONF = config.CONF def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine endpoint_table = sql.Table('endpoint', meta, autoload=True) session = orm.sessionmaker(bind=migrate_engine)() for endpoint in session.query(endpoint_table).all(): try: extra = json.loads(endpoint.extra) legacy_endpoint_id = extra.pop('legacy_endpoint_id') except KeyError: # if there is no legacy_endpoint_id, there's nothing to do pass else: q = endpoint_table.update() q = q.where(endpoint_table.c.id == endpoint.id) q = q.values({ endpoint_table.c.extra: json.dumps(extra), endpoint_table.c.legacy_endpoint_id: legacy_endpoint_id}) migrate_engine.execute(q) session.close() def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine endpoint_table = sql.Table('endpoint', meta, autoload=True) session = orm.sessionmaker(bind=migrate_engine)() for endpoint in session.query(endpoint_table).all(): if endpoint.legacy_endpoint_id is not None: extra = json.loads(endpoint.extra) extra['legacy_endpoint_id'] = endpoint.legacy_endpoint_id q = endpoint_table.update() q = q.where(endpoint_table.c.id == endpoint.id) q = q.values({ endpoint_table.c.extra: json.dumps(extra), endpoint_table.c.legacy_endpoint_id: None}) migrate_engine.execute(q) session.close() keystone-2014.1/keystone/common/sql/migrate_repo/versions/004_undo_token_id_hash.py0000664000175400017540000000267312323716272031653 0ustar jenkinsjenkins00000000000000# Copyright (c) 2012 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 sqlalchemy import Column, MetaData, String, Table def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine token = Table('token', meta, autoload=True) old_id_col = token.c.id old_id_col.alter(name='id_hash') # Note: We obtain a new metadata reference to avoid # sqlalchemy.exc.ArgumentError: # Trying to redefine primary-key column 'id' as a non-primary-key... meta = MetaData() meta.bind = migrate_engine token = Table('token', meta, autoload=True) new_id = Column("id", String(2048)) token.create_column(new_id) def upgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine token = Table('token', meta, autoload=True) token.drop_column('id') token = Table('token', meta, autoload=True) id_col = token.c.id_hash id_col.alter(name='id') keystone-2014.1/keystone/common/sql/migrate_repo/versions/010_normalize_identity_migration.py0000664000175400017540000000707412323716272034006 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import json import six from sqlalchemy import MetaData, Table from sqlalchemy.orm import sessionmaker DISABLED_VALUES = ['false', 'disabled', 'no', '0'] def is_enabled(enabled): # no explicit value means enabled if enabled is True or enabled is None: return True if (isinstance(enabled, six.string_types) and enabled.lower() in DISABLED_VALUES): return False return bool(enabled) def downgrade_user_table(meta, migrate_engine, session): user_table = Table('user', meta, autoload=True) for user in session.query(user_table).all(): extra = json.loads(user.extra) extra['password'] = user.password extra['enabled'] = '%r' % is_enabled(user.enabled) values = {'extra': json.dumps(extra)} update = user_table.update().\ where(user_table.c.id == user.id).\ values(values) migrate_engine.execute(update) def downgrade_tenant_table(meta, migrate_engine, session): tenant_table = Table('tenant', meta, autoload=True) for tenant in session.query(tenant_table).all(): extra = json.loads(tenant.extra) extra['description'] = tenant.description extra['enabled'] = '%r' % is_enabled(tenant.enabled) values = {'extra': json.dumps(extra)} update = tenant_table.update().\ where(tenant_table.c.id == tenant.id).\ values(values) migrate_engine.execute(update) def upgrade_user_table(meta, migrate_engine, session): user_table = Table('user', meta, autoload=True) for user in session.query(user_table).all(): extra = json.loads(user.extra) values = {'password': extra.pop('password', None), 'enabled': is_enabled(extra.pop('enabled', True)), 'extra': json.dumps(extra)} update = user_table.update().\ where(user_table.c.id == user.id).\ values(values) migrate_engine.execute(update) def upgrade_tenant_table(meta, migrate_engine, session): tenant_table = Table('tenant', meta, autoload=True) for tenant in session.query(tenant_table): extra = json.loads(tenant.extra) values = {'description': extra.pop('description', None), 'enabled': is_enabled(extra.pop('enabled', True)), 'extra': json.dumps(extra)} update = tenant_table.update().\ where(tenant_table.c.id == tenant.id).\ values(values) migrate_engine.execute(update) def upgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine session = sessionmaker(bind=migrate_engine)() upgrade_user_table(meta, migrate_engine, session) upgrade_tenant_table(meta, migrate_engine, session) session.commit() def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine session = sessionmaker(bind=migrate_engine)() downgrade_user_table(meta, migrate_engine, session) downgrade_tenant_table(meta, migrate_engine, session) session.commit() keystone-2014.1/keystone/common/sql/migrate_repo/versions/043_fixup_region_description.py0000664000175400017540000000644612323716267033141 0ustar jenkinsjenkins00000000000000# Copyright 2014 IBM Corp. # # 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. """Relax the uniqueness of `description` column in region table. The region table has a dedicated column for the region `description`. This column originally was not nullable and had to be unique. So if a user wanted to create a region without sending a `description` in the request, they would experience an SQL error because the `description` column can't be null for a region. This means that every region had to have a unique description. To upgrade, we are going to transfer all the data from the existing region table to a temporary table, drop the original region table, and then finally rename the temporary table to the correct name. There is no downgrade path as the original migration has been fixed to not include the unique constraint on description column. """ import migrate import sqlalchemy as sql from sqlalchemy.orm import sessionmaker _TEMP_REGION_TABLE_NAME = 'temp_region' _REGION_TABLE_NAME = 'region' def _migrate_to_new_region_table(meta, migrate_engine, region_table): # Create a temporary region table to hold data while we recreate the # new region table without a unique constraint on the description column session = sessionmaker(bind=migrate_engine)() temp_region_table = sql.Table( _TEMP_REGION_TABLE_NAME, meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('description', sql.String(255), nullable=False), sql.Column('parent_region_id', sql.String(64), nullable=True), sql.Column('extra', sql.Text())) temp_region_table.create(migrate_engine, checkfirst=True) # Migrate the data for region in list(session.query(region_table)): session.execute(temp_region_table.insert().values( id=region.id, description=region.description, parent_region_id=region.parent_region_id, extra=region.extra)) session.commit() session.close() # Drop the old region table region_table.drop(checkfirst=True) migrate.rename_table(temp_region_table, _REGION_TABLE_NAME, meta.bind) def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine region_table = sql.Table(_REGION_TABLE_NAME, meta, autoload=True) for idx in region_table.indexes: if ((idx.columns.get('description') == region_table.c.description) and len(idx.columns) is 1): # Constraint was found, do the migration. _migrate_to_new_region_table(meta, migrate_engine, region_table) break def downgrade(migrate_engine): # There is no downgrade option. The unique constraint should not have # existed and therefore does not need to be re-added. The previous # migration has been modified to not contain the unique constraint. pass keystone-2014.1/keystone/common/sql/migrate_repo/versions/038_add_assignment_table.py0000664000175400017540000000353312323716267032165 0ustar jenkinsjenkins00000000000000# Copyright 2014 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql from keystone.assignment.backends import sql as assignment_sql ASSIGNMENT_TABLE = 'assignment' def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine sql.Table('role', meta, autoload=True) assignment_table = sql.Table( ASSIGNMENT_TABLE, meta, sql.Column('type', sql.Enum( assignment_sql.AssignmentType.USER_PROJECT, assignment_sql.AssignmentType.GROUP_PROJECT, assignment_sql.AssignmentType.USER_DOMAIN, assignment_sql.AssignmentType.GROUP_DOMAIN, name='type'), nullable=False), sql.Column('actor_id', sql.String(64), nullable=False), sql.Column('target_id', sql.String(64), nullable=False), sql.Column('role_id', sql.String(64), sql.ForeignKey('role.id'), nullable=False), sql.Column('inherited', sql.Boolean, default=False, nullable=False), sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id')) assignment_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine assignment = sql.Table(ASSIGNMENT_TABLE, meta, autoload=True) assignment.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/common/sql/migrate_repo/versions/__init__.py0000664000175400017540000000000012323716267027165 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/sql/migrate_repo/versions/003_sqlite_upgrade.sql0000664000175400017540000000010312323716272031167 0ustar jenkinsjenkins00000000000000alter TABLE token ADD valid integer; update token set valid = 1; keystone-2014.1/keystone/common/sql/migrate_repo/versions/031_drop_credential_indexes.py0000664000175400017540000000257112323716272032701 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy def upgrade(migrate_engine): #This migration is relevant only for mysql because for all other #migrate engines these indexes were successfully dropped. if migrate_engine.name != 'mysql': return meta = sqlalchemy.MetaData(bind=migrate_engine) table = sqlalchemy.Table('credential', meta, autoload=True) for index in table.indexes: index.drop() def downgrade(migrate_engine): if migrate_engine.name != 'mysql': return meta = sqlalchemy.MetaData(bind=migrate_engine) table = sqlalchemy.Table('credential', meta, autoload=True) index = sqlalchemy.Index('user_id', table.c['user_id']) index.create() index = sqlalchemy.Index('credential_project_id_fkey', table.c['project_id']) index.create() keystone-2014.1/keystone/common/sql/migrate_repo/manage.py0000664000175400017540000000016412323716267025021 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python from migrate.versioning.shell import main if __name__ == '__main__': main(debug='False') keystone-2014.1/keystone/common/sql/migrate_repo/README0000664000175400017540000000015312323716267024075 0ustar jenkinsjenkins00000000000000This is a database migration repository. More information at http://code.google.com/p/sqlalchemy-migrate/ keystone-2014.1/keystone/common/sql/migrate_repo/migrate.cfg0000664000175400017540000000231412323716267025327 0ustar jenkinsjenkins00000000000000[db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. repository_id=keystone # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. # If this is changed once a database is under version control, you'll need to # change the table name in each database too. version_table=migrate_version # When committing a change script, Migrate will attempt to generate the # sql for all supported databases; normally, if one of them fails - probably # because you don't have that database installed - it is ignored and the # commit continues, perhaps ending successfully. # Databases in this list MUST compile successfully during a commit, or the # entire commit will fail. List the databases your application will actually # be using to ensure your updates to that database work properly. # This must be a list; example: ['postgres','sqlite'] required_dbs=[] # When creating new change scripts, Migrate will stamp the new script with # a version number. By default this is latest_version + 1. You can set this # to 'true' to tell Migrate to use the UTC timestamp instead. use_timestamp_numbering=False keystone-2014.1/keystone/common/sql/migrate_repo/__init__.py0000664000175400017540000000000012323716267025315 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/sql/migration_helpers.py0000664000175400017540000001352512323716272024630 0ustar jenkinsjenkins00000000000000# Copyright 2013 OpenStack Foundation # Copyright 2013 Red Hat, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import os import sys import migrate from migrate import exceptions import sqlalchemy from keystone.common import sql from keystone import contrib from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils # Different RDBMSs use different schemes for naming the Foreign Key # Constraints. SQLAlchemy does not yet attempt to determine the name # for the constraint, and instead attempts to deduce it from the column. # This fails on MySQL. def get_constraints_names(table, column_name): fkeys = [fk.name for fk in table.constraints if (column_name in fk.columns and isinstance(fk, sqlalchemy.ForeignKeyConstraint))] return fkeys # remove_constraints and add_constraints both accept a list of dictionaries # that contain: # {'table': a sqlalchemy table. The constraint is added to to dropped from # this table. # 'fk_column': the name of a column on the above table, The constraint # is added to or dropped from this column # 'ref_column':a sqlalchemy column object. This is the reference column # for the constraint. def remove_constraints(constraints): for constraint_def in constraints: constraint_names = get_constraints_names(constraint_def['table'], constraint_def['fk_column']) for constraint_name in constraint_names: migrate.ForeignKeyConstraint( columns=[getattr(constraint_def['table'].c, constraint_def['fk_column'])], refcolumns=[constraint_def['ref_column']], name=constraint_name).drop() def add_constraints(constraints): for constraint_def in constraints: if constraint_def['table'].kwargs.get('mysql_engine') == 'MyISAM': # Don't try to create constraint when using MyISAM because it's # not supported. continue ref_col = constraint_def['ref_column'] ref_engine = ref_col.table.kwargs.get('mysql_engine') if ref_engine == 'MyISAM': # Don't try to create constraint when using MyISAM because it's # not supported. continue migrate.ForeignKeyConstraint( columns=[getattr(constraint_def['table'].c, constraint_def['fk_column'])], refcolumns=[constraint_def['ref_column']]).create() def rename_tables_with_constraints(renames, constraints, engine): """Renames tables with foreign key constraints. Tables are renamed after first removing constraints. The constraints are replaced after the rename is complete. This works on databases that don't support renaming tables that have constraints on them (DB2). `renames` is a dict, mapping {'to_table_name': from_table, ...} """ if engine.name != 'sqlite': # Sqlite doesn't support constraints, so nothing to remove. remove_constraints(constraints) for to_table_name in renames: from_table = renames[to_table_name] from_table.rename(to_table_name) if engine != 'sqlite': add_constraints(constraints) def find_migrate_repo(package=None, repo_name='migrate_repo'): package = package or sql path = os.path.abspath(os.path.join( os.path.dirname(package.__file__), repo_name)) if os.path.isdir(path): return path raise exception.MigrationNotProvided(package.__name__, path) def sync_database_to_version(extension=None, version=None): if not extension: abs_path = find_migrate_repo() else: try: package_name = '.'.join((contrib.__name__, extension)) package = importutils.import_module(package_name) except ImportError: raise ImportError(_("%s extension does not exist.") % package_name) try: abs_path = find_migrate_repo(package) try: migration.db_version_control(sql.get_engine(), abs_path) # Register the repo with the version control API # If it already knows about the repo, it will throw # an exception that we can safely ignore except exceptions.DatabaseAlreadyControlledError: pass except exception.MigrationNotProvided as e: print(e) sys.exit(1) migration.db_sync(sql.get_engine(), abs_path, version=version) def get_db_version(extension=None): if not extension: return migration.db_version(sql.get_engine(), find_migrate_repo(), 0) try: package_name = '.'.join((contrib.__name__, extension)) package = importutils.import_module(package_name) except ImportError: raise ImportError(_("%s extension does not exist.") % package_name) return migration.db_version( sql.get_engine(), find_migrate_repo(package), 0) def print_db_version(extension=None): try: db_version = get_db_version(extension=extension) print(db_version) except exception.MigrationNotProvided as e: print(e) sys.exit(1) keystone-2014.1/keystone/common/sql/__init__.py0000664000175400017540000000120112323716272022640 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.common.sql.core import * keystone-2014.1/keystone/common/authorization.py0000664000175400017540000000755312323716272023222 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 - 2012 Justin Santa Barbara # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import collections from keystone.contrib import federation from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log AUTH_CONTEXT_ENV = 'KEYSTONE_AUTH_CONTEXT' """Environment variable used to convey the Keystone auth context. Auth context is essentially the user credential used for policy enforcement. It is a dictionary with the following attributes: * ``user_id``: user ID of the principal * ``project_id`` (optional): project ID of the scoped project if auth is project-scoped * ``domain_id`` (optional): domain ID of the scoped domain if auth is domain-scoped * ``roles`` (optional): list of role names for the given scope * ``group_ids``: list of group IDs for which the API user has membership """ LOG = log.getLogger(__name__) def flatten(d, parent_key=''): """Flatten a nested dictionary Converts a dictionary with nested values to a single level flat dictionary, with dotted notation for each key. """ items = [] for k, v in d.items(): new_key = parent_key + '.' + k if parent_key else k if isinstance(v, collections.MutableMapping): items.extend(flatten(v, new_key).items()) else: items.append((new_key, v)) return dict(items) def is_v3_token(token): # V3 token data are encapsulated into "token" key while # V2 token data are encapsulated into "access" key. return 'token' in token def v3_token_to_auth_context(token): creds = {} token_data = token['token'] try: creds['user_id'] = token_data['user']['id'] except AttributeError: LOG.warning(_('RBAC: Invalid user data in v3 token')) raise exception.Unauthorized() if 'project' in token_data: creds['project_id'] = token_data['project']['id'] else: LOG.debug(_('RBAC: Proceeding without project')) if 'domain' in token_data: creds['domain_id'] = token_data['domain']['id'] if 'roles' in token_data: creds['roles'] = [] for role in token_data['roles']: creds['roles'].append(role['name']) creds['group_ids'] = [ g['id'] for g in token_data['user'].get(federation.FEDERATION, {}).get( 'groups', [])] return creds def v2_token_to_auth_context(token): creds = {} token_data = token['access'] try: creds['user_id'] = token_data['user']['id'] except AttributeError: LOG.warning(_('RBAC: Invalid user data in v2 token')) raise exception.Unauthorized() if 'tenant' in token_data['token']: creds['project_id'] = token_data['token']['tenant']['id'] else: LOG.debug(_('RBAC: Proceeding without tenant')) if 'roles' in token_data['user']: creds['roles'] = [role['name'] for role in token_data['user']['roles']] return creds def token_to_auth_context(token): if is_v3_token(token): creds = v3_token_to_auth_context(token) else: creds = v2_token_to_auth_context(token) return creds keystone-2014.1/keystone/common/driver_hints.py0000664000175400017540000000622612323716267023022 0ustar jenkinsjenkins00000000000000# Copyright 2013 OpenStack Foundation # Copyright 2013 IBM Corp. # # 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. class Hints(list): """Encapsulate driver hints for listing entities. Hints are modifiers that affect the return of entities from a list_ operation. They are typically passed to a driver to give direction as to what filtering, pagination or list limiting actions are being requested. It is optional for a driver to action some or all of the list hints, but any filters that it does satisfy must be marked as such by calling removing the filter from the list. A Hint object is a list of dicts, initially of type 'filter' or 'limit', although other types may be added in the future. The list can be enumerated directly, or by using the filters() method which will guarantee to only return filters. """ def add_filter(self, name, value, comparator='equals', case_sensitive=False): self.append({'name': name, 'value': value, 'comparator': comparator, 'case_sensitive': case_sensitive, 'type': 'filter'}) def filters(self): """Iterate over all unsatisfied filters. Each filter term consists of: * ``name``: the name of the attribute being matched * ``value``: the value against which it is being matched * ``comparator``: the operation, which can be one of ``equals``, ``startswith`` or ``endswith`` * ``case_sensitive``: whether any comparison should take account of case * ``type``: will always be 'filter' """ return [x for x in self if x['type'] == 'filter'] def get_exact_filter_by_name(self, name): """Return a filter key and value if exact filter exists for name.""" for entry in self: if (entry['type'] == 'filter' and entry['name'] == name and entry['comparator'] == 'equals'): return entry def set_limit(self, limit, truncated=False): """Set a limit to indicate the list should be truncated.""" # We only allow one limit entry in the list, so if it already exists # we overwrite the old one for x in self: if x['type'] == 'limit': x['limit'] = limit x['truncated'] = truncated break else: self.append({'limit': limit, 'type': 'limit', 'truncated': truncated}) def get_limit(self): """Get the limit to which the list should be truncated.""" for x in self: if x['type'] == 'limit': return x keystone-2014.1/keystone/common/manager.py0000664000175400017540000000570112323716272021725 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import functools from keystone.openstack.common import importutils def response_truncated(f): """Truncate the list returned by the wrapped function. This is designed to wrap Manager list_{entity} methods to ensure that any list limits that are defined are passed to the driver layer. If a hints list is provided, the wrapper will insert the relevant limit into the hints so that the underlying driver call can try and honor it. If the driver does truncate the response, it will update the 'truncated' attribute in the 'limit' entry in the hints list, which enables the caller of this function to know if truncation has taken place. If, however, the driver layer is unable to perform truncation, the 'limit' entry is simply left in the hints list for the caller to handle. A _get_list_limit() method is required to be present in the object class hierarchy, which returns the limit for this backend to which we will truncate. If a hints list is not provided in the arguments of the wrapped call then any limits set in the config file are ignored. This allows internal use of such wrapped methods where the entire data set is needed as input for the calculations of some other API (e.g. get role assignments for a given project). """ @functools.wraps(f) def wrapper(self, *args, **kwargs): if kwargs.get('hints') is None: return f(self, *args, **kwargs) list_limit = self.driver._get_list_limit() if list_limit: kwargs['hints'].set_limit(list_limit) return f(self, *args, **kwargs) return wrapper class Manager(object): """Base class for intermediary request layer. The Manager layer exists to support additional logic that applies to all or some of the methods exposed by a service that are not specific to the HTTP interface. It also provides a stable entry point to dynamic backends. An example of a probable use case is logging all the calls. """ def __init__(self, driver_name): self.driver = importutils.import_object(driver_name) def __getattr__(self, name): """Forward calls to the underlying driver.""" f = getattr(self.driver, name) @functools.wraps(f) def _wrapper(*args, **kw): return f(*args, **kw) setattr(self, name, _wrapper) return _wrapper keystone-2014.1/keystone/common/wsgi.py0000664000175400017540000005424412323716272021272 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2010 OpenStack Foundation # All Rights Reserved. # # 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. """Utility methods for working with WSGI servers.""" import routes.middleware import six import webob.dec import webob.exc from keystone.common import config from keystone.common import dependency from keystone.common import utils from keystone import exception from keystone.openstack.common import gettextutils from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone.openstack.common import jsonutils from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) # Environment variable used to pass the request context CONTEXT_ENV = 'openstack.context' # Environment variable used to pass the request params PARAMS_ENV = 'openstack.params' def validate_token_bind(context, token_ref): bind_mode = CONF.token.enforce_token_bind if bind_mode == 'disabled': return bind = token_ref.get('bind', {}) # permissive and strict modes don't require there to be a bind permissive = bind_mode in ('permissive', 'strict') # get the named mode if bind_mode is not one of the known name = None if permissive or bind_mode == 'required' else bind_mode if not bind: if permissive: # no bind provided and none required return else: LOG.info(_("No bind information present in token")) raise exception.Unauthorized() if name and name not in bind: LOG.info(_("Named bind mode %s not in bind information"), name) raise exception.Unauthorized() for bind_type, identifier in six.iteritems(bind): if bind_type == 'kerberos': if not (context['environment'].get('AUTH_TYPE', '').lower() == 'negotiate'): LOG.info(_("Kerberos credentials required and not present")) raise exception.Unauthorized() if not context['environment'].get('REMOTE_USER') == identifier: LOG.info(_("Kerberos credentials do not match those in bind")) raise exception.Unauthorized() LOG.info(_("Kerberos bind authentication successful")) elif bind_mode == 'permissive': LOG.debug(_("Ignoring unknown bind for permissive mode: " "{%(bind_type)s: %(identifier)s}"), {'bind_type': bind_type, 'identifier': identifier}) else: LOG.info(_("Couldn't verify unknown bind: " "{%(bind_type)s: %(identifier)s}"), {'bind_type': bind_type, 'identifier': identifier}) raise exception.Unauthorized() def best_match_language(req): """Determines the best available locale from the Accept-Language HTTP header passed in the request. """ if not req.accept_language: return None return req.accept_language.best_match( gettextutils.get_available_languages('keystone')) class BaseApplication(object): """Base WSGI application wrapper. Subclasses need to implement __call__.""" @classmethod def factory(cls, global_config, **local_config): """Used for paste app factories in paste.deploy config files. Any local configuration (that is, values under the [app:APPNAME] section of the paste config) will be passed into the `__init__` method as kwargs. A hypothetical configuration would look like: [app:wadl] latest_version = 1.3 paste.app_factory = keystone.fancy_api:Wadl.factory which would result in a call to the `Wadl` class as import keystone.fancy_api keystone.fancy_api.Wadl(latest_version='1.3') You could of course re-implement the `factory` method in subclasses, but using the kwarg passing it shouldn't be necessary. """ return cls(**local_config) def __call__(self, environ, start_response): r"""Subclasses will probably want to implement __call__ like this: @webob.dec.wsgify() def __call__(self, req): # Any of the following objects work as responses: # Option 1: simple string res = 'message\n' # Option 2: a nicely formatted HTTP exception page res = exc.HTTPForbidden(explanation='Nice try') # Option 3: a webob Response object (in case you need to play with # headers, or you want to be treated like an iterable, or or or) res = Response(); res.app_iter = open('somefile') # Option 4: any wsgi app to be run next res = self.application # Option 5: you can get a Response object for a wsgi app, too, to # play with headers etc res = req.get_response(self.application) # You can then just return your response... return res # ... or set req.response and return None. req.response = res See the end of http://pythonpaste.org/webob/modules/dec.html for more info. """ raise NotImplementedError('You must implement __call__') @dependency.requires('assignment_api', 'policy_api', 'token_api') class Application(BaseApplication): @webob.dec.wsgify() def __call__(self, req): arg_dict = req.environ['wsgiorg.routing_args'][1] action = arg_dict.pop('action') del arg_dict['controller'] LOG.debug(_('arg_dict: %s'), arg_dict) # allow middleware up the stack to provide context, params and headers. context = req.environ.get(CONTEXT_ENV, {}) context['query_string'] = dict(six.iteritems(req.params)) context['headers'] = dict(six.iteritems(req.headers)) context['path'] = req.environ['PATH_INFO'] context['host_url'] = req.host_url params = req.environ.get(PARAMS_ENV, {}) #authentication and authorization attributes are set as environment #values by the container and processed by the pipeline. the complete #set is not yet know. context['environment'] = req.environ req.environ = None params.update(arg_dict) context.setdefault('is_admin', False) # TODO(termie): do some basic normalization on methods method = getattr(self, action) # NOTE(vish): make sure we have no unicode keys for py2.6. params = self._normalize_dict(params) try: result = method(context, **params) except exception.Unauthorized as e: LOG.warning( _('Authorization failed. %(exception)s from %(remote_addr)s'), {'exception': e, 'remote_addr': req.environ['REMOTE_ADDR']}) return render_exception(e, context=context, user_locale=best_match_language(req)) except exception.Error as e: LOG.warning(e) return render_exception(e, context=context, user_locale=best_match_language(req)) except TypeError as e: LOG.exception(e) return render_exception(exception.ValidationError(e), context=context, user_locale=best_match_language(req)) except Exception as e: LOG.exception(e) return render_exception(exception.UnexpectedError(exception=e), context=context, user_locale=best_match_language(req)) if result is None: return render_response(status=(204, 'No Content')) elif isinstance(result, six.string_types): return result elif isinstance(result, webob.Response): return result elif isinstance(result, webob.exc.WSGIHTTPException): return result response_code = self._get_response_code(req) return render_response(body=result, status=response_code) def _get_response_code(self, req): req_method = req.environ['REQUEST_METHOD'] controller = importutils.import_class('keystone.common.controller') code = None if isinstance(self, controller.V3Controller) and req_method == 'POST': code = (201, 'Created') return code def _normalize_arg(self, arg): return str(arg).replace(':', '_').replace('-', '_') def _normalize_dict(self, d): return dict([(self._normalize_arg(k), v) for (k, v) in six.iteritems(d)]) def assert_admin(self, context): if not context['is_admin']: try: user_token_ref = self.token_api.get_token(context['token_id']) except exception.TokenNotFound as e: raise exception.Unauthorized(e) validate_token_bind(context, user_token_ref) creds = user_token_ref['metadata'].copy() try: creds['user_id'] = user_token_ref['user'].get('id') except AttributeError: LOG.debug('Invalid user') raise exception.Unauthorized() try: creds['tenant_id'] = user_token_ref['tenant'].get('id') except AttributeError: LOG.debug('Invalid tenant') raise exception.Unauthorized() # NOTE(vish): this is pretty inefficient creds['roles'] = [self.assignment_api.get_role(role)['name'] for role in creds.get('roles', [])] # Accept either is_admin or the admin role self.policy_api.enforce(creds, 'admin_required', {}) def _require_attribute(self, ref, attr): """Ensures the reference contains the specified attribute.""" if ref.get(attr) is None or ref.get(attr) == '': msg = _('%s field is required and cannot be empty') % attr raise exception.ValidationError(message=msg) def _get_trust_id_for_request(self, context): """Get the trust_id for a call. Retrieve the trust_id from the token Returns None if token is is not trust scoped """ if ('token_id' not in context or context.get('token_id') == CONF.admin_token): LOG.debug(_('will not lookup trust as the request auth token is ' 'either absent or it is the system admin token')) return None try: token_ref = self.token_api.get_token(context['token_id']) except exception.TokenNotFound: LOG.warning(_('Invalid token in _get_trust_id_for_request')) raise exception.Unauthorized() return token_ref.get('trust_id') @classmethod def base_url(cls, context, endpoint_type): url = CONF['%s_endpoint' % endpoint_type] if url: url = url % CONF else: # NOTE(jamielennox): if url is not set via the config file we # should set it relative to the url that the user used to get here # so as not to mess with version discovery. This is not perfect. # host_url omits the path prefix, but there isn't another good # solution that will work for all urls. url = context['host_url'] return url.rstrip('/') class Middleware(Application): """Base WSGI middleware. These classes require an application to be initialized that will be called next. By default the middleware will simply call its wrapped app, or you can override __call__ to customize its behavior. """ @classmethod def factory(cls, global_config, **local_config): """Used for paste app factories in paste.deploy config files. Any local configuration (that is, values under the [filter:APPNAME] section of the paste config) will be passed into the `__init__` method as kwargs. A hypothetical configuration would look like: [filter:analytics] redis_host = 127.0.0.1 paste.filter_factory = keystone.analytics:Analytics.factory which would result in a call to the `Analytics` class as import keystone.analytics keystone.analytics.Analytics(app, redis_host='127.0.0.1') You could of course re-implement the `factory` method in subclasses, but using the kwarg passing it shouldn't be necessary. """ def _factory(app): conf = global_config.copy() conf.update(local_config) return cls(app, **local_config) return _factory def __init__(self, application): super(Middleware, self).__init__() self.application = application def process_request(self, request): """Called on each request. If this returns None, the next application down the stack will be executed. If it returns a response then that response will be returned and execution will stop here. """ return None def process_response(self, request, response): """Do whatever you'd like to the response, based on the request.""" return response @webob.dec.wsgify() def __call__(self, request): try: response = self.process_request(request) if response: return response response = request.get_response(self.application) return self.process_response(request, response) except exception.Error as e: LOG.warning(e) return render_exception(e, request=request, user_locale=best_match_language(request)) except TypeError as e: LOG.exception(e) return render_exception(exception.ValidationError(e), request=request, user_locale=best_match_language(request)) except Exception as e: LOG.exception(e) return render_exception(exception.UnexpectedError(exception=e), request=request, user_locale=best_match_language(request)) class Debug(Middleware): """Helper class for debugging a WSGI application. Can be inserted into any WSGI application chain to get information about the request and response. """ @webob.dec.wsgify() def __call__(self, req): if not hasattr(LOG, 'isEnabledFor') or LOG.isEnabledFor(LOG.debug): LOG.debug('%s %s %s', ('*' * 20), 'REQUEST ENVIRON', ('*' * 20)) for key, value in req.environ.items(): LOG.debug('%s = %s', key, log.mask_password(value)) LOG.debug('') LOG.debug('%s %s %s', ('*' * 20), 'REQUEST BODY', ('*' * 20)) for line in req.body_file: LOG.debug('%s', log.mask_password(line)) LOG.debug('') resp = req.get_response(self.application) if not hasattr(LOG, 'isEnabledFor') or LOG.isEnabledFor(LOG.debug): LOG.debug('%s %s %s', ('*' * 20), 'RESPONSE HEADERS', ('*' * 20)) for (key, value) in six.iteritems(resp.headers): LOG.debug('%s = %s', key, value) LOG.debug('') resp.app_iter = self.print_generator(resp.app_iter) return resp @staticmethod def print_generator(app_iter): """Iterator that prints the contents of a wrapper string.""" LOG.debug('%s %s %s', ('*' * 20), 'RESPONSE BODY', ('*' * 20)) for part in app_iter: LOG.debug(part) yield part class Router(object): """WSGI middleware that maps incoming requests to WSGI apps.""" def __init__(self, mapper): """Create a router for the given routes.Mapper. Each route in `mapper` must specify a 'controller', which is a WSGI app to call. You'll probably want to specify an 'action' as well and have your controller be an object that can route the request to the action-specific method. Examples: mapper = routes.Mapper() sc = ServerController() # Explicit mapping of one route to a controller+action mapper.connect(None, '/svrlist', controller=sc, action='list') # Actions are all implicitly defined mapper.resource('server', 'servers', controller=sc) # Pointing to an arbitrary WSGI app. You can specify the # {path_info:.*} parameter so the target app can be handed just that # section of the URL. mapper.connect(None, '/v1.0/{path_info:.*}', controller=BlogApp()) """ self.map = mapper self._router = routes.middleware.RoutesMiddleware(self._dispatch, self.map) @webob.dec.wsgify() def __call__(self, req): """Route the incoming request to a controller based on self.map. If no match, return a 404. """ return self._router @staticmethod @webob.dec.wsgify() def _dispatch(req): """Dispatch the request to the appropriate controller. Called by self._router after matching the incoming request to a route and putting the information into req.environ. Either returns 404 or the routed WSGI app's response. """ match = req.environ['wsgiorg.routing_args'][1] if not match: msg = _('The resource could not be found.') return render_exception(exception.NotFound(msg), request=req, user_locale=best_match_language(req)) app = match['controller'] return app class ComposingRouter(Router): def __init__(self, mapper=None, routers=None): if mapper is None: mapper = routes.Mapper() if routers is None: routers = [] for router in routers: router.add_routes(mapper) super(ComposingRouter, self).__init__(mapper) class ComposableRouter(Router): """Router that supports use by ComposingRouter.""" def __init__(self, mapper=None): if mapper is None: mapper = routes.Mapper() self.add_routes(mapper) super(ComposableRouter, self).__init__(mapper) def add_routes(self, mapper): """Add routes to given mapper.""" pass class ExtensionRouter(Router): """A router that allows extensions to supplement or overwrite routes. Expects to be subclassed. """ def __init__(self, application, mapper=None): if mapper is None: mapper = routes.Mapper() self.application = application self.add_routes(mapper) mapper.connect('{path_info:.*}', controller=self.application) super(ExtensionRouter, self).__init__(mapper) def add_routes(self, mapper): pass @classmethod def factory(cls, global_config, **local_config): """Used for paste app factories in paste.deploy config files. Any local configuration (that is, values under the [filter:APPNAME] section of the paste config) will be passed into the `__init__` method as kwargs. A hypothetical configuration would look like: [filter:analytics] redis_host = 127.0.0.1 paste.filter_factory = keystone.analytics:Analytics.factory which would result in a call to the `Analytics` class as import keystone.analytics keystone.analytics.Analytics(app, redis_host='127.0.0.1') You could of course re-implement the `factory` method in subclasses, but using the kwarg passing it shouldn't be necessary. """ def _factory(app): conf = global_config.copy() conf.update(local_config) return cls(app, **local_config) return _factory def render_response(body=None, status=None, headers=None): """Forms a WSGI response.""" headers = headers or [] headers.append(('Vary', 'X-Auth-Token')) if body is None: body = '' status = status or (204, 'No Content') else: body = jsonutils.dumps(body, cls=utils.SmarterEncoder) headers.append(('Content-Type', 'application/json')) status = status or (200, 'OK') return webob.Response(body=body, status='%s %s' % status, headerlist=headers) def render_exception(error, context=None, request=None, user_locale=None): """Forms a WSGI response based on the current error.""" error_message = error.args[0] message = gettextutils.translate(error_message, desired_locale=user_locale) if message is error_message: # translate() didn't do anything because it wasn't a Message, # convert to a string. message = six.text_type(message) body = {'error': { 'code': error.code, 'title': error.title, 'message': message, }} headers = [] if isinstance(error, exception.AuthPluginException): body['error']['identity'] = error.authentication elif isinstance(error, exception.Unauthorized): url = CONF.public_endpoint if not url: if request: context = {'host_url': request.host_url} if context: url = Application.base_url(context, 'public') else: url = 'http://localhost:%d' % CONF.public_port else: url = url % CONF headers.append(('WWW-Authenticate', 'Keystone uri="%s"' % url)) return render_response(status=(error.code, error.title), body=body, headers=headers) keystone-2014.1/keystone/common/systemd.py0000664000175400017540000000221512323716267022004 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """ Helper module for systemd start-up completion notification. Used for "onready" configuration parameter in keystone.conf """ import os import socket def _sd_notify(msg): sysd = os.getenv('NOTIFY_SOCKET') if sysd: sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) if sysd.startswith('@'): # abstract namespace socket sysd = '\0%s' % sysd[1:] sock.connect(sysd) sock.sendall(msg) sock.close() def notify(): _sd_notify('READY=1') if __name__ == '__main__': notify() keystone-2014.1/keystone/common/environment/0000775000175400017540000000000012323716511022276 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/environment/eventlet_server.py0000664000175400017540000001106012323716267026072 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import socket import ssl import sys import eventlet import eventlet.wsgi import greenlet from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log LOG = log.getLogger(__name__) class Server(object): """Server class to manage multiple WSGI sockets and applications.""" def __init__(self, application, host=None, port=None, threads=1000, keepalive=False, keepidle=None): self.application = application self.host = host or '0.0.0.0' self.port = port or 0 self.pool = eventlet.GreenPool(threads) self.socket_info = {} self.greenthread = None self.do_ssl = False self.cert_required = False self.keepalive = keepalive self.keepidle = keepidle def start(self, key=None, backlog=128): """Run a WSGI server with the given application.""" LOG.info(_('Starting %(arg0)s on %(host)s:%(port)s'), {'arg0': sys.argv[0], 'host': self.host, 'port': self.port}) # TODO(dims): eventlet's green dns/socket module does not actually # support IPv6 in getaddrinfo(). We need to get around this in the # future or monitor upstream for a fix info = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM)[0] _socket = eventlet.listen(info[-1], family=info[0], backlog=backlog) if key: self.socket_info[key] = _socket.getsockname() # SSL is enabled if self.do_ssl: if self.cert_required: cert_reqs = ssl.CERT_REQUIRED else: cert_reqs = ssl.CERT_NONE sslsocket = eventlet.wrap_ssl(_socket, certfile=self.certfile, keyfile=self.keyfile, server_side=True, cert_reqs=cert_reqs, ca_certs=self.ca_certs) _socket = sslsocket # Optionally enable keepalive on the wsgi socket. if self.keepalive: _socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # This option isn't available in the OS X version of eventlet if hasattr(socket, 'TCP_KEEPIDLE') and self.keepidle is not None: _socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, self.keepidle) self.greenthread = self.pool.spawn(self._run, self.application, _socket) def set_ssl(self, certfile, keyfile=None, ca_certs=None, cert_required=True): self.certfile = certfile self.keyfile = keyfile self.ca_certs = ca_certs self.cert_required = cert_required self.do_ssl = True def kill(self): if self.greenthread is not None: self.greenthread.kill() def wait(self): """Wait until all servers have completed running.""" try: self.pool.waitall() except KeyboardInterrupt: pass except greenlet.GreenletExit: pass def _run(self, application, socket): """Start a WSGI server in a new green thread.""" logger = log.getLogger('eventlet.wsgi.server') try: eventlet.wsgi.server(socket, application, custom_pool=self.pool, log=log.WritableLogger(logger), debug=False) except Exception: LOG.exception(_('Server error')) raise keystone-2014.1/keystone/common/environment/__init__.py0000664000175400017540000000645612323716272024426 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import functools import os from keystone.common import config from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) __all__ = ['Server', 'httplib', 'subprocess'] _configured = False Server = None httplib = None subprocess = None def configure_once(name): """Ensure that environment configuration is only run once. If environment is reconfigured in the same way then it is ignored. It is an error to attempt to reconfigure environment in a different way. """ def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): global _configured if _configured: if _configured == name: return else: raise SystemError("Environment has already been " "configured as %s" % _configured) LOG.info(_("Environment configured as: %s"), name) _configured = name return func(*args, **kwargs) return wrapper return decorator @configure_once('eventlet') def use_eventlet(monkeypatch_thread=None): global httplib, subprocess, Server # This must be set before the initial import of eventlet because if # dnspython is present in your environment then eventlet monkeypatches # socket.getaddrinfo() with an implementation which doesn't work for IPv6. os.environ['EVENTLET_NO_GREENDNS'] = 'yes' import eventlet from eventlet.green import httplib as _httplib from eventlet.green import subprocess as _subprocess from keystone.common.environment import eventlet_server if monkeypatch_thread is None: monkeypatch_thread = not os.getenv('STANDARD_THREADS') # Raise the default from 8192 to accommodate large tokens eventlet.wsgi.MAX_HEADER_LINE = 16384 # NOTE(ldbragst): Explicitly declare what should be monkey patched and # what shouldn't. Doing this allows for more readable code when # understanding Eventlet in Keystone. The following is a complete list # of what is monkey patched instead of passing all=False and then passing # module=True to monkey patch a specific module. eventlet.patcher.monkey_patch(os=False, select=True, socket=True, thread=monkeypatch_thread, time=True, psycopg=False, MySQLdb=False) Server = eventlet_server.Server httplib = _httplib subprocess = _subprocess @configure_once('stdlib') def use_stdlib(): global httplib, subprocess import httplib as _httplib import subprocess as _subprocess httplib = _httplib subprocess = _subprocess keystone-2014.1/keystone/common/pemutils.py0000775000175400017540000004272312323716272022165 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """ PEM formatted data is used frequently in conjunction with X509 PKI as a data exchange mechanism for binary data. The acronym PEM stands for Privacy Enhanced Mail as defined in RFC-1421. Contrary to expectation the PEM format in common use has little to do with RFC-1421. Instead what we know as PEM format grew out of the need for a data exchange mechanism largely by the influence of OpenSSL. Other X509 implementations have adopted it. Unfortunately PEM format has never been officially standarized. It's basic format is as follows: 1) A header consisting of 5 hyphens followed by the word BEGIN and a single space. Then an upper case string describing the contents of the PEM block, this is followed by 5 hyphens and a newline. 2) Binary data (typically in DER ASN.1 format) encoded in base64. The base64 text is line wrapped so that each line of base64 is 64 characters long and terminated with a newline. The last line of base64 text may be less than 64 characters. The content and format of the binary data is entirely dependent upon the type of data announced in the header and footer. 3) A footer in the exact same as the header except the word BEGIN is replaced by END. The content name in both the header and footer should exactly match. The above is called a PEM block. It is permissible for multiple PEM blocks to appear in a single file or block of text. This is often used when specifying multiple X509 certificates. An example PEM block for a certificate is: -----BEGIN CERTIFICATE----- MIIC0TCCAjqgAwIBAgIJANsHKV73HYOwMA0GCSqGSIb3DQEBBQUAMIGeMQowCAYD VQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55 dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMG CSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2Vs ZiBTaWduZWQwIBcNMTIxMTA1MTgxODI0WhgPMjA3MTA0MzAxODE4MjRaMIGeMQow CAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1 bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTEl MCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxML U2VsZiBTaWduZWQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALzI17ExCaqd r7xY2Q5CBZ1bW1lsrXxS8eNJRdQtskDuQVAluY03/OGZd8HQYiiY/ci2tYy7BNIC bh5GaO95eqTDykJR3liOYE/tHbY6puQlj2ZivmhlSd2d5d7lF0/H28RQsLu9VktM uw6q9DpDm35jfrr8LgSeA3MdVqcS/4OhAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB Af8wDQYJKoZIhvcNAQEFBQADgYEAjSQND7i1dNZtLKpWgX+JqMr3BdVlM15mFeVr C26ZspZjZVY5okdozO9gU3xcwRe4Cg30sKFOe6EBQKpkTZucFOXwBtD3h6dWJrdD c+m/CL/rs0GatDavbaIT2vv405SQUQooCdVh72LYel+4/a6xmRd7fQx3iEXN9QYj vmHJUcA= -----END CERTIFICATE----- PEM format is safe for transmission in 7-bit ASCII systems (i.e. standard email). Since 7-bit ASCII is a proper subset of UTF-8 and Latin-1 it is not affected by transcoding between those charsets. Nor is PEM format affected by the choice of line endings. This makes PEM format particularity attractive for transport and storage of binary data. This module provides a number of utilities supporting the generation and consumption of PEM formatted data including: * parse text and find all PEM blocks contained in the text. Information on the location of the block in the text, the type of PEM block, and it's base64 and binary data contents. * parse text assumed to contain PEM data and return the binary data. * test if a block of text is a PEM block * convert base64 text into a formatted PEM block * convert binary data into a formatted PEM block * access to the valid PEM types and their headers """ import base64 import re import six from keystone.common import base64utils from keystone.openstack.common.gettextutils import _ PEM_TYPE_TO_HEADER = { u'cms': u'CMS', u'dsa-private': u'DSA PRIVATE KEY', u'dsa-public': u'DSA PUBLIC KEY', u'ecdsa-public': u'ECDSA PUBLIC KEY', u'ec-private': u'EC PRIVATE KEY', u'pkcs7': u'PKCS7', u'pkcs7-signed': u'PKCS', u'pkcs8': u'ENCRYPTED PRIVATE KEY', u'private-key': u'PRIVATE KEY', u'public-key': u'PUBLIC KEY', u'rsa-private': u'RSA PRIVATE KEY', u'rsa-public': u'RSA PUBLIC KEY', u'cert': u'CERTIFICATE', u'crl': u'X509 CRL', u'cert-pair': u'CERTIFICATE PAIR', u'csr': u'CERTIFICATE REQUEST', } # This is not a 1-to-1 reverse map of PEM_TYPE_TO_HEADER # because it includes deprecated headers that map to 1 pem_type. PEM_HEADER_TO_TYPE = { u'CMS': u'cms', u'DSA PRIVATE KEY': u'dsa-private', u'DSA PUBLIC KEY': u'dsa-public', u'ECDSA PUBLIC KEY': u'ecdsa-public', u'EC PRIVATE KEY': u'ec-private', u'PKCS7': u'pkcs7', u'PKCS': u'pkcs7-signed', u'ENCRYPTED PRIVATE KEY': u'pkcs8', u'PRIVATE KEY': u'private-key', u'PUBLIC KEY': u'public-key', u'RSA PRIVATE KEY': u'rsa-private', u'RSA PUBLIC KEY': u'rsa-public', u'CERTIFICATE': u'cert', u'X509 CERTIFICATE': u'cert', u'CERTIFICATE PAIR': u'cert-pair', u'X509 CRL': u'crl', u'CERTIFICATE REQUEST': u'csr', u'NEW CERTIFICATE REQUEST': u'csr', } # List of valid pem_types pem_types = sorted(PEM_TYPE_TO_HEADER.keys()) # List of valid pem_headers pem_headers = sorted(PEM_TYPE_TO_HEADER.values()) _pem_begin_re = re.compile(r'^-{5}BEGIN\s+([^-]+)-{5}\s*$', re.MULTILINE) _pem_end_re = re.compile(r'^-{5}END\s+([^-]+)-{5}\s*$', re.MULTILINE) class PEMParseResult(object): """Information returned when a PEM block is found in text. PEMParseResult contains information about a PEM block discovered while parsing text. The following properties are defined: pem_type A short hand name for the type of the PEM data, e.g. cert, csr, crl, cms, key. Valid pem_types are listed in pem_types. When the pem_type is set the pem_header is updated to match it. pem_header The text following '-----BEGIN ' in the PEM header. Common examples are: -----BEGIN CERTIFICATE----- -----BEGIN CMS----- Thus the pem_header would be CERTIFICATE and CMS respectively. When the pem_header is set the pem_type is updated to match it. pem_start, pem_end The beginning and ending positions of the PEM block including the PEM header and footer. base64_start, base64_end The beginning and ending positions of the base64 data contained inside the PEM header and footer. Includes trailing new line binary_data The decoded base64 data. None if not decoded. """ def __init__(self, pem_type=None, pem_header=None, pem_start=None, pem_end=None, base64_start=None, base64_end=None, binary_data=None): self._pem_type = None self._pem_header = None if pem_type is not None: self.pem_type = pem_type if pem_header is not None: self.pem_header = pem_header self.pem_start = pem_start self.pem_end = pem_end self.base64_start = base64_start self.base64_end = base64_end self.binary_data = binary_data @property def pem_type(self): return self._pem_type @pem_type.setter def pem_type(self, pem_type): if pem_type is None: self._pem_type = None self._pem_header = None else: pem_header = PEM_TYPE_TO_HEADER.get(pem_type) if pem_header is None: raise ValueError(_('unknown pem_type "%(pem_type)s", ' 'valid types are: %(valid_pem_types)s') % {'pem_type': pem_type, 'valid_pem_types': ', '.join(pem_types)}) self._pem_type = pem_type self._pem_header = pem_header @property def pem_header(self): return self._pem_header @pem_header.setter def pem_header(self, pem_header): if pem_header is None: self._pem_type = None self._pem_header = None else: pem_type = PEM_HEADER_TO_TYPE.get(pem_header) if pem_type is None: raise ValueError(_('unknown pem header "%(pem_header)s", ' 'valid headers are: ' '%(valid_pem_headers)s') % {'pem_header': pem_header, 'valid_pem_headers': ', '.join("'%s'" % [x for x in pem_headers])}) self._pem_type = pem_type self._pem_header = pem_header #------------------------------------------------------------------------------ def pem_search(text, start=0): """Search for a block of PEM formatted data Search for a PEM block in a text string. The search begins at start. If a PEM block is found a PEMParseResult object is returned, otherwise if no PEM block is found None is returned. If the pem_type is not the same in both the header and footer a ValueError is raised. The start and end positions are suitable for use as slices into the text. To search for multiple PEM blocks pass pem_end as the start position for the next iteration. Terminate the iteration when None is returned. Example:: start = 0 while True: block = pem_search(text, start) if block is None: break base64_data = text[block.base64_start : block.base64_end] start = block.pem_end :param text: the text to search for PEM blocks :type text: string :param start: the position in text to start searching from (default: 0) :type start: int :returns: PEMParseResult or None if not found :raises: ValueError """ match = _pem_begin_re.search(text, pos=start) if match: pem_start = match.start() begin_text = match.group(0) base64_start = min(len(text), match.end() + 1) begin_pem_header = match.group(1).strip() match = _pem_end_re.search(text, pos=base64_start) if match: pem_end = min(len(text), match.end() + 1) base64_end = match.start() end_pem_header = match.group(1).strip() else: raise ValueError(_('failed to find end matching "%s"') % begin_text) if begin_pem_header != end_pem_header: raise ValueError(_('beginning & end PEM headers do not match ' '(%(begin_pem_header)s' '!= ' '%(end_pem_header)s)') % {'begin_pem_header': begin_pem_header, 'end_pem_header': end_pem_header}) else: return None result = PEMParseResult(pem_header=begin_pem_header, pem_start=pem_start, pem_end=pem_end, base64_start=base64_start, base64_end=base64_end) return result def parse_pem(text, pem_type=None, max_items=None): """Scan text for PEM data, return list of PEM items The input text is scanned for PEM blocks, for each one found a PEMParseResult is contructed and added to the return list. pem_type operates as a filter on the type of PEM desired. If pem_type is specified only those PEM blocks which match will be included. The pem_type is a logical name, not the actual text in the pem header (e.g. 'cert'). If the pem_type is None all PEM blocks are returned. If max_items is specified the result is limited to that number of items. The return value is a list of PEMParseResult objects. The PEMParseResult provides complete information about the PEM block including the decoded binary data for the PEM block. The list is ordered in the same order as found in the text. Examples:: # Get all certs certs = parse_pem(text, 'cert') # Get the first cert try: binary_cert = parse_pem(text, 'cert', 1)[0].binary_data except IndexError: raise ValueError('no cert found') :param text: The text to search for PEM blocks :type text: string :param pem_type: Only return data for this pem_type. Valid types are: csr, cert, crl, cms, key. If pem_type is None no filtering is performed. (default: None) :type pem_type: string or None :param max_items: Limit the number of blocks returned. (default: None) :type max_items: int or None :return: List of PEMParseResult, one for each PEM block found :raises: ValueError, InvalidBase64Error """ pem_blocks = [] start = 0 while True: block = pem_search(text, start) if block is None: break start = block.pem_end if pem_type is None: pem_blocks.append(block) else: try: if block.pem_type == pem_type: pem_blocks.append(block) except KeyError: raise ValueError(_('unknown pem_type: "%s"') % (pem_type)) if max_items is not None and len(pem_blocks) >= max_items: break for block in pem_blocks: base64_data = text[block.base64_start:block.base64_end] try: binary_data = base64.b64decode(base64_data) except Exception as e: block.binary_data = None raise base64utils.InvalidBase64Error( _('failed to base64 decode %(pem_type)s PEM at position' '%(position)d: %(err_msg)s') % {'pem_type': block.pem_type, 'position': block.pem_start, 'err_msg': six.text_type(e)}) else: block.binary_data = binary_data return pem_blocks def get_pem_data(text, pem_type='cert'): """Scan text for PEM data, return binary contents The input text is scanned for a PEM block which matches the pem_type. If found the binary data contained in the PEM block is returned. If no PEM block is found or it does not match the specified pem type None is returned. :param text: The text to search for the PEM block :type text: string :param pem_type: Only return data for this pem_type. Valid types are: csr, cert, crl, cms, key. (default: 'cert') :type pem_type: string :return: binary data or None if not found. """ blocks = parse_pem(text, pem_type, 1) if not blocks: return None return blocks[0].binary_data def is_pem(text, pem_type='cert'): """Does this text contain a PEM block. Check for the existence of a PEM formatted block in the text, if one is found verify it's contents can be base64 decoded, if so return True. Return False otherwise. :param text: The text to search for PEM blocks :type text: string :param pem_type: Only return data for this pem_type. Valid types are: csr, cert, crl, cms, key. (default: 'cert') :type pem_type: string :returns: bool -- True if text contains PEM matching the pem_type, False otherwise. """ try: pem_blocks = parse_pem(text, pem_type, max_items=1) except base64utils.InvalidBase64Error: return False if pem_blocks: return True else: return False def base64_to_pem(base64_text, pem_type='cert'): """Format string of base64 text into PEM format Input is assumed to consist only of members of the base64 alphabet (i.e no whitepace). Use one of the filter functions from base64utils to assure the input is clean (i.e. strip_whitespace()). :param base64_text: text containing ONLY base64 alphabet characters to be inserted into PEM output. :type base64_text: string :param pem_type: Produce a PEM block for this type. Valid types are: csr, cert, crl, cms, key. (default: 'cert') :type pem_type: string :returns: string -- PEM formatted text """ pem_header = PEM_TYPE_TO_HEADER[pem_type] buf = six.StringIO() buf.write(u'-----BEGIN %s-----' % pem_header) buf.write(u'\n') for line in base64utils.base64_wrap_iter(base64_text, width=64): buf.write(line) buf.write(u'\n') buf.write(u'-----END %s-----' % pem_header) buf.write(u'\n') text = buf.getvalue() buf.close() return text def binary_to_pem(binary_data, pem_type='cert'): """Format binary data into PEM format Example: # get the certificate binary data in DER format der_data = certificate.der # convert the DER binary data into a PEM pem = binary_to_pem(der_data, 'cert') :param binary_data: binary data to encapsulate into PEM :type binary_data: buffer :param pem_type: Produce a PEM block for this type. Valid types are: csr, cert, crl, cms, key. (default: 'cert') :type pem_type: string :returns: string -- PEM formatted text """ base64_text = base64.b64encode(binary_data) return base64_to_pem(base64_text, pem_type) keystone-2014.1/keystone/common/utils.py0000664000175400017540000004203512323716272021454 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 - 2012 Justin Santa Barbara # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import calendar import grp import hashlib import json import os import pwd import passlib.hash import six from keystone.common import config from keystone.common import environment from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import strutils from six import moves CONF = config.CONF LOG = log.getLogger(__name__) def read_cached_file(filename, cache_info, reload_func=None): """Read from a file if it has been modified. :param cache_info: dictionary to hold opaque cache. :param reload_func: optional function to be called with data when file is reloaded due to a modification. :returns: data from file. """ mtime = os.path.getmtime(filename) if not cache_info or mtime != cache_info.get('mtime'): with open(filename) as fap: cache_info['data'] = fap.read() cache_info['mtime'] = mtime if reload_func: reload_func(cache_info['data']) return cache_info['data'] class SmarterEncoder(json.JSONEncoder): """Help for JSON encoding dict-like objects.""" def default(self, obj): if not isinstance(obj, dict) and hasattr(obj, 'iteritems'): return dict(obj.iteritems()) return super(SmarterEncoder, self).default(obj) def trunc_password(password): """Truncate passwords to the max_length.""" max_length = CONF.identity.max_password_length try: if len(password) > max_length: LOG.warning( _('Truncating user password to %s characters.'), max_length) return password[:max_length] except TypeError: raise exception.ValidationError(attribute='string', target='password') def hash_access_key(access): hash_ = hashlib.sha256() hash_.update(access) return hash_.hexdigest() def hash_user_password(user): """Hash a user dict's password without modifying the passed-in dict.""" password = user.get('password') if password is None: return user return dict(user, password=hash_password(password)) def hash_ldap_user_password(user): """Hash a user dict's password without modifying the passed-in dict.""" password = user.get('password') if password is None: return user return dict(user, password=ldap_hash_password(password)) def hash_password(password): """Hash a password. Hard.""" password_utf8 = trunc_password(password).encode('utf-8') return passlib.hash.sha512_crypt.encrypt( password_utf8, rounds=CONF.crypt_strength) def ldap_hash_password(password): """Hash a password. Hard.""" password_utf8 = trunc_password(password).encode('utf-8') h = passlib.hash.ldap_salted_sha1.encrypt(password_utf8) return h def ldap_check_password(password, hashed): if password is None: return False password_utf8 = trunc_password(password).encode('utf-8') return passlib.hash.ldap_salted_sha1.verify(password_utf8, hashed) def check_password(password, hashed): """Check that a plaintext password matches hashed. hashpw returns the salt value concatenated with the actual hash value. It extracts the actual salt if this value is then passed as the salt. """ if password is None or hashed is None: return False password_utf8 = trunc_password(password).encode('utf-8') return passlib.hash.sha512_crypt.verify(password_utf8, hashed) def attr_as_boolean(val_attr): """Returns the boolean value, decoded from a string. We test explicitly for a value meaning False, which can be one of several formats as specified in oslo strutils.FALSE_STRINGS. All other string values (including an empty string) are treated as meaning True. """ return strutils.bool_from_string(val_attr, default=True) # From python 2.7 def check_output(*popenargs, **kwargs): r"""Run command with arguments and return its output as a byte string. If the exit code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and output in the output attribute. The arguments are the same as for the Popen constructor. Example: >>> check_output(['ls', '-l', '/dev/null']) 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' The stdout argument is not allowed as it is used internally. To capture standard error in the result, use stderr=STDOUT. >>> import sys >>> check_output(['/bin/sh', '-c', ... 'ls -l non_existent_file ; exit 0'], ... stderr=sys.STDOUT) 'ls: non_existent_file: No such file or directory\n' """ if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') LOG.debug(' '.join(popenargs[0])) process = environment.subprocess.Popen(stdout=environment.subprocess.PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get('args') if cmd is None: cmd = popenargs[0] raise environment.subprocess.CalledProcessError(retcode, cmd) return output def get_blob_from_credential(credential): try: blob = json.loads(credential.blob) except (ValueError, TypeError): raise exception.ValidationError( message=_('Invalid blob in credential')) if not blob or not isinstance(blob, dict): raise exception.ValidationError(attribute='blob', target='credential') return blob def convert_ec2_to_v3_credential(ec2credential): blob = {'access': ec2credential.access, 'secret': ec2credential.secret} return {'id': hash_access_key(ec2credential.access), 'user_id': ec2credential.user_id, 'project_id': ec2credential.tenant_id, 'blob': json.dumps(blob), 'type': 'ec2', 'extra': json.dumps({})} def convert_v3_to_ec2_credential(credential): blob = get_blob_from_credential(credential) return {'access': blob.get('access'), 'secret': blob.get('secret'), 'user_id': credential.user_id, 'tenant_id': credential.project_id, } def git(*args): return check_output(['git'] + list(args)) def unixtime(dt_obj): """Format datetime object as unix timestamp :param dt_obj: datetime.datetime object :returns: float """ return calendar.timegm(dt_obj.utctimetuple()) def auth_str_equal(provided, known): """Constant-time string comparison. :params provided: the first string :params known: the second string :return: True if the strings are equal. This function takes two strings and compares them. It is intended to be used when doing a comparison for authentication purposes to help guard against timing attacks. When using the function for this purpose, always provide the user-provided password as the first argument. The time this function will take is always a factor of the length of this string. """ result = 0 p_len = len(provided) k_len = len(known) for i in moves.range(p_len): a = ord(provided[i]) if i < p_len else 0 b = ord(known[i]) if i < k_len else 0 result |= a ^ b return (p_len == k_len) & (result == 0) def setup_remote_pydev_debug(): if CONF.pydev_debug_host and CONF.pydev_debug_port: try: try: from pydev import pydevd except ImportError: import pydevd pydevd.settrace(CONF.pydev_debug_host, port=CONF.pydev_debug_port, stdoutToServer=True, stderrToServer=True) return True except Exception: LOG.exception(_( 'Error setting up the debug environment. Verify that the ' 'option --debug-url has the format : and that a ' 'debugger processes is listening on that port.')) raise class LimitingReader(object): """Reader to limit the size of an incoming request.""" def __init__(self, data, limit): """Create an iterator on the underlying data. :param data: Underlying data object :param limit: maximum number of bytes the reader should allow """ self.data = data self.limit = limit self.bytes_read = 0 def __iter__(self): for chunk in self.data: self.bytes_read += len(chunk) if self.bytes_read > self.limit: raise exception.RequestTooLarge() else: yield chunk def read(self, i=None): # NOTE(jamielennox): We can't simply provide the default to the read() # call as the expected default differs between mod_wsgi and eventlet if i is None: result = self.data.read() else: result = self.data.read(i) self.bytes_read += len(result) if self.bytes_read > self.limit: raise exception.RequestTooLarge() return result def get_unix_user(user=None): '''Get the uid and user name. This is a convenience utility which accepts a variety of input which might represent a unix user. If successful it returns the uid and name. Valid input is: string A string is first considered to be a user name and a lookup is attempted under that name. If no name is found then an attempt is made to convert the string to an integer and perform a lookup as a uid. int An integer is interpretted as a uid. None None is interpreted to mean use the current process's effective user. If the input is a valid type but no user is found a KeyError is raised. If the input is not a valid type a TypeError is raised. :param object user: string, int or None specifying the user to lookup. :return: tuple of (uid, name) ''' if isinstance(user, six.string_types): try: user_info = pwd.getpwnam(user) except KeyError: try: i = int(user) except ValueError: raise KeyError("user name '%s' not found" % user) try: user_info = pwd.getpwuid(i) except KeyError: raise KeyError("user id %d not found" % i) elif isinstance(user, int): try: user_info = pwd.getpwuid(user) except KeyError: raise KeyError("user id %d not found" % user) elif user is None: user_info = pwd.getpwuid(os.geteuid()) else: raise TypeError('user must be string, int or None; not %s (%r)' % (user.__class__.__name__, user)) return user_info.pw_uid, user_info.pw_name def get_unix_group(group=None): '''Get the gid and group name. This is a convenience utility which accepts a variety of input which might represent a unix group. If successful it returns the gid and name. Valid input is: string A string is first considered to be a group name and a lookup is attempted under that name. If no name is found then an attempt is made to convert the string to an integer and perform a lookup as a gid. int An integer is interpretted as a gid. None None is interpreted to mean use the current process's effective group. If the input is a valid type but no group is found a KeyError is raised. If the input is not a valid type a TypeError is raised. :param object group: string, int or None specifying the group to lookup. :return: tuple of (gid, name) ''' if isinstance(group, six.string_types): try: group_info = grp.getgrnam(group) except KeyError: # Was an int passed as a string? # Try converting to int and lookup by id instead. try: i = int(group) except ValueError: raise KeyError("group name '%s' not found" % group) try: group_info = grp.getgrgid(i) except KeyError: raise KeyError("group id %d not found" % i) elif isinstance(group, int): try: group_info = grp.getgrgid(group) except KeyError: raise KeyError("group id %d not found" % group) elif group is None: group_info = grp.getgrgid(os.getegid()) else: raise TypeError('group must be string, int or None; not %s (%r)' % (group.__class__.__name__, group)) return group_info.gr_gid, group_info.gr_name def set_permissions(path, mode=None, user=None, group=None, log=None): '''Set the ownership and permissions on the pathname. Each of the mode, user and group are optional, if None then that aspect is not modified. Owner and group may be specified either with a symbolic name or numeric id. :param string path: Pathname of directory whose existence is assured. :param object mode: ownership permissions flags (int) i.e. chmod, if None do not set. :param object user: set user, name (string) or uid (integer), if None do not set. :param object group: set group, name (string) or gid (integer) if None do not set. :param logger log: logging.logger object, used to emit log messages, if None no logging is performed. ''' if user is None: user_uid, user_name = None, None else: user_uid, user_name = get_unix_user(user) if group is None: group_gid, group_name = None, None else: group_gid, group_name = get_unix_group(group) if log: if mode is None: mode_string = str(mode) else: mode_string = oct(mode) log.debug("set_permissions: " "path='%s' mode=%s user=%s(%s) group=%s(%s)", path, mode_string, user_name, user_uid, group_name, group_gid) # Change user and group if specified if user_uid is not None or group_gid is not None: if user_uid is None: user_uid = -1 if group_gid is None: group_gid = -1 try: os.chown(path, user_uid, group_gid) except OSError as exc: raise EnvironmentError("chown('%s', %s, %s): %s" % (path, user_name, group_name, exc.strerror)) # Change permission flags if mode is not None: try: os.chmod(path, mode) except OSError as exc: raise EnvironmentError("chmod('%s', %#o): %s" % (path, mode, exc.strerror)) def make_dirs(path, mode=None, user=None, group=None, log=None): '''Assure directory exists, set ownership and permissions. Assure the directory exists and optionally set it's ownership and permissions. Each of the mode, user and group are optional, if None then that aspect is not modified. Owner and group may be specified either with a symbolic name or numeric id. :param string path: Pathname of directory whose existence is assured. :param object mode: ownership permissions flags (int) i.e. chmod, if None do not set. :param object user: set user, name (string) or uid (integer), if None do not set. :param object group: set group, name (string) or gid (integer) if None do not set. :param logger log: logging.logger object, used to emit log messages, if None no logging is performed. ''' if log: if mode is None: mode_string = str(mode) else: mode_string = oct(mode) log.debug("make_dirs path='%s' mode=%s user=%s group=%s", path, mode_string, user, group) if not os.path.exists(path): try: os.makedirs(path) except OSError as exc: raise EnvironmentError("makedirs('%s'): %s" % (path, exc.strerror)) set_permissions(path, mode, user, group, log) keystone-2014.1/keystone/common/config.py0000664000175400017540000011742612323716272021570 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from oslo.config import cfg _DEFAULT_AUTH_METHODS = ['external', 'password', 'token'] FILE_OPTIONS = { None: [ cfg.StrOpt('admin_token', secret=True, default='ADMIN', help='A "shared secret" that can be used to bootstrap ' 'Keystone. This "token" does not represent a user, ' 'and carries no explicit authorization. To disable ' 'in production (highly recommended), remove ' 'AdminTokenAuthMiddleware from your paste ' 'application pipelines (for example, in ' 'keystone-paste.ini).'), cfg.StrOpt('public_bind_host', default='0.0.0.0', deprecated_opts=[cfg.DeprecatedOpt('bind_host', group='DEFAULT')], help='The IP Address of the network interface to for the ' 'public service to listen on.'), cfg.StrOpt('admin_bind_host', default='0.0.0.0', deprecated_opts=[cfg.DeprecatedOpt('bind_host', group='DEFAULT')], help='The IP Address of the network interface to for the ' 'admin service to listen on.'), cfg.IntOpt('compute_port', default=8774, help='The port which the OpenStack Compute service ' 'listens on.'), cfg.IntOpt('admin_port', default=35357, help='The port number which the admin service listens ' 'on.'), cfg.IntOpt('public_port', default=5000, help='The port number which the public service listens ' 'on.'), cfg.StrOpt('public_endpoint', help='The base public endpoint URL for keystone that are ' 'advertised to clients (NOTE: this does NOT affect ' 'how keystone listens for connections). ' 'Defaults to the base host URL of the request. Eg a ' 'request to http://server:5000/v2.0/users will ' 'default to http://server:5000. You should only need ' 'to set this value if the base URL contains a path ' '(eg /prefix/v2.0) or the endpoint should be found on ' 'a different server.'), cfg.StrOpt('admin_endpoint', help='The base admin endpoint URL for keystone that are ' 'advertised to clients (NOTE: this does NOT affect ' 'how keystone listens for connections). ' 'Defaults to the base host URL of the request. Eg a ' 'request to http://server:35357/v2.0/users will ' 'default to http://server:35357. You should only need ' 'to set this value if the base URL contains a path ' '(eg /prefix/v2.0) or the endpoint should be found on ' 'a different server.'), cfg.StrOpt('onready', help='onready allows you to send a notification when the ' 'process is ready to serve For example, to have it ' 'notify using systemd, one could set shell command: ' '"onready = systemd-notify --ready" or a module ' 'with notify() method: ' '"onready = keystone.common.systemd".'), # default max request size is 112k cfg.IntOpt('max_request_body_size', default=114688, help='enforced by optional sizelimit middleware ' '(keystone.middleware:RequestBodySizeLimiter).'), cfg.IntOpt('max_param_size', default=64, help='limit the sizes of user & tenant ID/names.'), # we allow tokens to be a bit larger to accommodate PKI cfg.IntOpt('max_token_size', default=8192, help='similar to max_param_size, but provides an ' 'exception for token values.'), cfg.StrOpt('member_role_id', default='9fe2ff9ee4384b1894a90878d3e92bab', help='During a SQL upgrade member_role_id will be used ' 'to create a new role that will replace records in ' 'the user_tenant_membership table with explicit ' 'role grants. After migration, the member_role_id ' 'will be used in the API add_user_to_project.'), cfg.StrOpt('member_role_name', default='_member_', help='During a SQL upgrade member_role_id will be used ' 'to create a new role that will replace records in ' 'the user_tenant_membership table with explicit ' 'role grants. After migration, member_role_name will ' 'be ignored.'), cfg.IntOpt('crypt_strength', default=40000, help='The value passed as the keyword "rounds" to passlib ' 'encrypt method.'), cfg.BoolOpt('tcp_keepalive', default=False, help='Set this to True if you want to enable ' 'TCP_KEEPALIVE on server sockets i.e. sockets used ' 'by the keystone wsgi server for client ' 'connections.'), cfg.IntOpt('tcp_keepidle', default=600, help='Sets the value of TCP_KEEPIDLE in seconds for each ' 'server socket. Only applies if tcp_keepalive is ' 'True. Not supported on OS X.'), cfg.IntOpt('list_limit', default=None, help='The maximum number of entities that will be ' 'returned in a collection can be set with ' 'list_limit, with no limit set by default. This ' 'global limit may be then overridden for a specific ' 'driver, by specifying a list_limit in the ' 'appropriate section (e.g. [assignment]).'), cfg.BoolOpt('domain_id_immutable', default=True, help='Set this to false if you want to enable the ' 'ability for user, group and project entities ' 'to be moved between domains by updating their ' 'domain_id. Allowing such movement is not ' 'recommended if the scope of a domain admin is being ' 'restricted by use of an appropriate policy file ' '(see policy.v3cloudsample as an example).')], 'identity': [ cfg.StrOpt('default_domain_id', default='default', help='This references the domain to use for all ' 'Identity API v2 requests (which are not aware of ' 'domains). A domain with this ID will be created ' 'for you by keystone-manage db_sync in migration ' '008. The domain referenced by this ID cannot be ' 'deleted on the v3 API, to prevent accidentally ' 'breaking the v2 API. There is nothing special about ' 'this domain, other than the fact that it must ' 'exist to order to maintain support for your v2 ' 'clients.'), cfg.BoolOpt('domain_specific_drivers_enabled', default=False, help='A subset (or all) of domains can have their own ' 'identity driver, each with their own partial ' 'configuration file in a domain configuration ' 'directory. Only values specific to the domain ' 'need to be placed in the domain specific ' 'configuration file. This feature is disabled by ' 'default; set to True to enable.'), cfg.StrOpt('domain_config_dir', default='/etc/keystone/domains', help='Path for Keystone to locate the domain specific' 'identity configuration files if ' 'domain_specific_drivers_enabled is set to true.'), cfg.StrOpt('driver', default=('keystone.identity.backends' '.sql.Identity'), help='Keystone Identity backend driver.'), cfg.IntOpt('max_password_length', default=4096, help='Maximum supported length for user passwords; ' 'decrease to improve performance.'), cfg.IntOpt('list_limit', default=None, help='Maximum number of entities that will be returned in ' 'an identity collection.')], 'trust': [ cfg.BoolOpt('enabled', default=True, help='delegation and impersonation features can be ' 'optionally disabled.'), cfg.StrOpt('driver', default='keystone.trust.backends.sql.Trust', help='Keystone Trust backend driver.')], 'os_inherit': [ cfg.BoolOpt('enabled', default=False, help='role-assignment inheritance to projects from ' 'owning domain can be optionally enabled.')], 'token': [ cfg.ListOpt('bind', default=[], help='External auth mechanisms that should add bind ' 'information to token e.g. kerberos, x509.'), cfg.StrOpt('enforce_token_bind', default='permissive', help='Enforcement policy on tokens presented to keystone ' 'with bind information. One of disabled, permissive, ' 'strict, required or a specifically required bind ' 'mode e.g. kerberos or x509 to require binding to ' 'that authentication.'), cfg.IntOpt('expiration', default=3600, help='Amount of time a token should remain valid ' '(in seconds).'), cfg.StrOpt('provider', default=None, help='Controls the token construction, validation, and ' 'revocation operations. Core providers are ' '"keystone.token.providers.[pki|uuid].Provider".'), cfg.StrOpt('driver', default='keystone.token.backends.sql.Token', help='Keystone Token persistence backend driver.'), cfg.BoolOpt('caching', default=True, help='Toggle for token system cacheing. This has no ' 'effect unless global caching is enabled.'), cfg.IntOpt('revocation_cache_time', default=3600, help='Time to cache the revocation list and the revocation ' 'events if revoke extension is enabled (in seconds). ' 'This has no effect unless global and token ' 'caching are enabled.'), cfg.IntOpt('cache_time', default=None, help='Time to cache tokens (in seconds). This has no ' 'effect unless global and token caching are ' 'enabled.'), cfg.BoolOpt('revoke_by_id', default=True, help='Revoke token by token identifier. Setting ' 'revoke_by_id to True enables various forms of ' 'enumerating tokens, e.g. `list tokens for user`. ' 'These enumerations are processed to determine the ' 'list of tokens to revoke. Only disable if you are ' 'switching to using the Revoke extension with a ' 'backend other than KVS, which stores events in memory.') ], 'revoke': [ cfg.StrOpt('driver', default='keystone.contrib.revoke.backends.kvs.Revoke', help='An implementation of the backend for persisting ' 'revocation events.'), cfg.IntOpt('expiration_buffer', default=1800, help='This value (calculated in seconds) is added to token ' 'expiration before a revocation event may be removed ' 'from the backend.'), cfg.BoolOpt('caching', default=True, help='Toggle for revocation event cacheing. This has no ' 'effect unless global caching is enabled.'), ], 'cache': [ cfg.StrOpt('config_prefix', default='cache.keystone', help='Prefix for building the configuration dictionary ' 'for the cache region. This should not need to be ' 'changed unless there is another dogpile.cache ' 'region with the same configuration name.'), cfg.IntOpt('expiration_time', default=600, help='Default TTL, in seconds, for any cached item in ' 'the dogpile.cache region. This applies to any ' 'cached method that doesn\'t have an explicit ' 'cache expiration time defined for it.'), # NOTE(morganfainberg): the dogpile.cache.memory acceptable in devstack # and other such single-process/thread deployments. Running # dogpile.cache.memory in any other configuration has the same pitfalls # as the KVS token backend. It is recommended that either Redis or # Memcached are used as the dogpile backend for real workloads. To # prevent issues with the memory cache ending up in "production" # unintentionally, we register a no-op as the keystone default caching # backend. cfg.StrOpt('backend', default='keystone.common.cache.noop', help='Dogpile.cache backend module. It is recommended ' 'that Memcache (dogpile.cache.memcache) or Redis ' '(dogpile.cache.redis) be used in production ' 'deployments. Small workloads (single process) ' 'like devstack can use the dogpile.cache.memory ' 'backend.'), cfg.BoolOpt('use_key_mangler', default=True, help='Use a key-mangling function (sha1) to ensure ' 'fixed length cache-keys. This is toggle-able for ' 'debugging purposes, it is highly recommended to ' 'always leave this set to True.'), cfg.MultiStrOpt('backend_argument', default=[], help='Arguments supplied to the backend module. ' 'Specify this option once per argument to be ' 'passed to the dogpile.cache backend. Example ' 'format: ":".'), cfg.ListOpt('proxies', default=[], help='Proxy Classes to import that will affect the way ' 'the dogpile.cache backend functions. See the ' 'dogpile.cache documentation on ' 'changing-backend-behavior. Comma delimited ' 'list e.g. ' 'my.dogpile.proxy.Class, my.dogpile.proxyClass2.'), cfg.BoolOpt('enabled', default=False, help='Global toggle for all caching using the ' 'should_cache_fn mechanism.'), cfg.BoolOpt('debug_cache_backend', default=False, help='Extra debugging from the cache backend (cache ' 'keys, get/set/delete/etc calls) This is only ' 'really useful if you need to see the specific ' 'cache-backend get/set/delete calls with the ' 'keys/values. Typically this should be left set ' 'to False.')], 'ssl': [ cfg.BoolOpt('enable', default=False, help='Toggle for SSL support on the keystone ' 'eventlet servers.'), cfg.StrOpt('certfile', default="/etc/keystone/ssl/certs/keystone.pem", help='Path of the certfile for SSL.'), cfg.StrOpt('keyfile', default='/etc/keystone/ssl/private/keystonekey.pem', help='Path of the keyfile for SSL.'), cfg.StrOpt('ca_certs', default='/etc/keystone/ssl/certs/ca.pem', help='Path of the ca cert file for SSL.'), cfg.StrOpt('ca_key', default='/etc/keystone/ssl/private/cakey.pem', help='Path of the CA key file for SSL.'), cfg.BoolOpt('cert_required', default=False, help='Require client certificate.'), cfg.IntOpt('key_size', default=1024, help='SSL Key Length (in bits) (auto generated ' 'certificate).'), cfg.IntOpt('valid_days', default=3650, help='Days the certificate is valid for once signed ' '(auto generated certificate).'), cfg.StrOpt('cert_subject', default='/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost', help='SSL Certificate Subject (auto generated ' 'certificate).')], 'signing': [ cfg.StrOpt('token_format', default=None, help='Deprecated in favor of provider in the ' '[token] section.'), cfg.StrOpt('certfile', default='/etc/keystone/ssl/certs/signing_cert.pem', help='Path of the certfile for token signing.'), cfg.StrOpt('keyfile', default='/etc/keystone/ssl/private/signing_key.pem', help='Path of the keyfile for token signing.'), cfg.StrOpt('ca_certs', default='/etc/keystone/ssl/certs/ca.pem', help='Path of the CA for token signing.'), cfg.StrOpt('ca_key', default='/etc/keystone/ssl/private/cakey.pem', help='Path of the CA Key for token signing.'), cfg.IntOpt('key_size', default=2048, help='Key Size (in bits) for token signing cert ' '(auto generated certificate).'), cfg.IntOpt('valid_days', default=3650, help='Day the token signing cert is valid for ' '(auto generated certificate).'), cfg.StrOpt('cert_subject', default=('/C=US/ST=Unset/L=Unset/O=Unset/' 'CN=www.example.com'), help='Certificate Subject (auto generated certificate) for ' 'token signing.')], 'assignment': [ # assignment has no default for backward compatibility reasons. # If assignment driver is not specified, the identity driver chooses # the backend cfg.StrOpt('driver', default=None, help='Keystone Assignment backend driver.'), cfg.BoolOpt('caching', default=True, help='Toggle for assignment caching. This has no effect ' 'unless global caching is enabled.'), cfg.IntOpt('cache_time', default=None, help='TTL (in seconds) to cache assignment data. This has ' 'no effect unless global caching is enabled.'), cfg.IntOpt('list_limit', default=None, help='Maximum number of entities that will be returned ' 'in an assignment collection.')], 'credential': [ cfg.StrOpt('driver', default=('keystone.credential.backends' '.sql.Credential'), help='Keystone Credential backend driver.')], 'oauth1': [ cfg.StrOpt('driver', default='keystone.contrib.oauth1.backends.sql.OAuth1', help='Keystone Credential backend driver.'), cfg.IntOpt('request_token_duration', default=28800, help='Duration (in seconds) for the OAuth Request Token.'), cfg.IntOpt('access_token_duration', default=86400, help='Duration (in seconds) for the OAuth Access Token.')], 'federation': [ cfg.StrOpt('driver', default='keystone.contrib.federation.' 'backends.sql.Federation', help='Keystone Federation backend driver.'), cfg.StrOpt('assertion_prefix', default='', help='Value to be used when filtering assertion parameters ' 'from the environment.')], 'policy': [ cfg.StrOpt('driver', default='keystone.policy.backends.sql.Policy', help='Keystone Policy backend driver.'), cfg.IntOpt('list_limit', default=None, help='Maximum number of entities that will be returned ' 'in a policy collection.')], 'ec2': [ cfg.StrOpt('driver', default='keystone.contrib.ec2.backends.kvs.Ec2', help='Keystone EC2Credential backend driver.')], 'endpoint_filter': [ cfg.StrOpt('driver', default='keystone.contrib.endpoint_filter.backends' '.sql.EndpointFilter', help='Keystone Endpoint Filter backend driver'), cfg.BoolOpt('return_all_endpoints_if_no_filter', default=True, help='Toggle to return all active endpoints if no filter ' 'exists.')], 'stats': [ cfg.StrOpt('driver', default=('keystone.contrib.stats.backends' '.kvs.Stats'), help='Keystone stats backend driver.')], 'ldap': [ cfg.StrOpt('url', default='ldap://localhost', help='URL for connecting to the LDAP server.'), cfg.StrOpt('user', default=None, help='User BindDN to query the LDAP server.'), cfg.StrOpt('password', secret=True, default=None, help='Password for the BindDN to query the LDAP server.'), cfg.StrOpt('suffix', default='cn=example,cn=com', help='LDAP server suffix'), cfg.BoolOpt('use_dumb_member', default=False, help='If true, will add a dummy member to groups. This is ' 'required if the objectclass for groups requires the ' '"member" attribute.'), cfg.StrOpt('dumb_member', default='cn=dumb,dc=nonexistent', help='DN of the "dummy member" to use when ' '"use_dumb_member" is enabled.'), cfg.BoolOpt('allow_subtree_delete', default=False, help='allow deleting subtrees.'), cfg.StrOpt('query_scope', default='one', help='The LDAP scope for queries, this can be either ' '"one" (onelevel/singleLevel) or "sub" ' '(subtree/wholeSubtree).'), cfg.IntOpt('page_size', default=0, help='Maximum results per page; a value of zero ("0") ' 'disables paging.'), cfg.StrOpt('alias_dereferencing', default='default', help='The LDAP dereferencing option for queries. This ' 'can be either "never", "searching", "always", ' '"finding" or "default". The "default" option falls ' 'back to using default dereferencing configured by ' 'your ldap.conf.'), cfg.BoolOpt('chase_referrals', default=None, help='Override the system\'s default referral chasing ' 'behavior for queries.'), cfg.StrOpt('user_tree_dn', default=None, help='Search base for users.'), cfg.StrOpt('user_filter', default=None, help='LDAP search filter for users.'), cfg.StrOpt('user_objectclass', default='inetOrgPerson', help='LDAP objectClass for users.'), cfg.StrOpt('user_id_attribute', default='cn', help='LDAP attribute mapped to user id.'), cfg.StrOpt('user_name_attribute', default='sn', help='LDAP attribute mapped to user name.'), cfg.StrOpt('user_mail_attribute', default='email', help='LDAP attribute mapped to user email.'), cfg.StrOpt('user_pass_attribute', default='userPassword', help='LDAP attribute mapped to password.'), cfg.StrOpt('user_enabled_attribute', default='enabled', help='LDAP attribute mapped to user enabled flag.'), cfg.IntOpt('user_enabled_mask', default=0, help='Bitmask integer to indicate the bit that the enabled ' 'value is stored in if the LDAP server represents ' '"enabled" as a bit on an integer rather than a ' 'boolean. A value of "0" indicates the mask is not ' 'used. If this is not set to "0" the typical value ' 'is "2". This is typically used when ' '"user_enabled_attribute = userAccountControl".'), cfg.StrOpt('user_enabled_default', default='True', help='Default value to enable users. This should match an ' 'appropriate int value if the LDAP server uses ' 'non-boolean (bitmask) values to indicate if a user ' 'is enabled or disabled. If this is not set to "True"' 'the typical value is "512". This is typically used ' 'when "user_enabled_attribute = userAccountControl".'), cfg.ListOpt('user_attribute_ignore', default=['default_project_id', 'tenants'], help='List of attributes stripped off the user on ' 'update.'), cfg.StrOpt('user_default_project_id_attribute', default=None, help='LDAP attribute mapped to default_project_id for ' 'users.'), cfg.BoolOpt('user_allow_create', default=True, help='Allow user creation in LDAP backend.'), cfg.BoolOpt('user_allow_update', default=True, help='Allow user updates in LDAP backend.'), cfg.BoolOpt('user_allow_delete', default=True, help='Allow user deletion in LDAP backend.'), cfg.BoolOpt('user_enabled_emulation', default=False, help='If True, Keystone uses an alternative method to ' 'determine if a user is enabled or not by checking ' 'if they are a member of the ' '"user_enabled_emulation_dn" group.'), cfg.StrOpt('user_enabled_emulation_dn', default=None, help='DN of the group entry to hold enabled users when ' 'using enabled emulation.'), cfg.ListOpt('user_additional_attribute_mapping', default=[], help='List of additional LDAP attributes used for mapping ' 'Additional attribute mappings for users. Attribute ' 'mapping format is :, where ' 'ldap_attr is the attribute in the LDAP entry and ' 'user_attr is the Identity API attribute.'), cfg.StrOpt('tenant_tree_dn', default=None, help='Search base for projects'), cfg.StrOpt('tenant_filter', default=None, help='LDAP search filter for projects.'), cfg.StrOpt('tenant_objectclass', default='groupOfNames', help='LDAP objectClass for projects.'), cfg.StrOpt('tenant_id_attribute', default='cn', help='LDAP attribute mapped to project id.'), cfg.StrOpt('tenant_member_attribute', default='member', help='LDAP attribute mapped to project membership for ' 'user.'), cfg.StrOpt('tenant_name_attribute', default='ou', help='LDAP attribute mapped to project name.'), cfg.StrOpt('tenant_desc_attribute', default='description', help='LDAP attribute mapped to project description.'), cfg.StrOpt('tenant_enabled_attribute', default='enabled', help='LDAP attribute mapped to project enabled.'), cfg.StrOpt('tenant_domain_id_attribute', default='businessCategory', help='LDAP attribute mapped to project domain_id.'), cfg.ListOpt('tenant_attribute_ignore', default=[], help='List of attributes stripped off the project on ' 'update.'), cfg.BoolOpt('tenant_allow_create', default=True, help='Allow tenant creation in LDAP backend.'), cfg.BoolOpt('tenant_allow_update', default=True, help='Allow tenant update in LDAP backend.'), cfg.BoolOpt('tenant_allow_delete', default=True, help='Allow tenant deletion in LDAP backend.'), cfg.BoolOpt('tenant_enabled_emulation', default=False, help='If True, Keystone uses an alternative method to ' 'determine if a project is enabled or not by ' 'checking if they are a member of the ' '"tenant_enabled_emulation_dn" group.'), cfg.StrOpt('tenant_enabled_emulation_dn', default=None, help='DN of the group entry to hold enabled projects when ' 'using enabled emulation.'), cfg.ListOpt('tenant_additional_attribute_mapping', default=[], help='Additional attribute mappings for projects. ' 'Attribute mapping format is ' ':, where ldap_attr is the ' 'attribute in the LDAP entry and user_attr is the ' 'Identity API attribute.'), cfg.StrOpt('role_tree_dn', default=None, help='Search base for roles.'), cfg.StrOpt('role_filter', default=None, help='LDAP search filter for roles.'), cfg.StrOpt('role_objectclass', default='organizationalRole', help='LDAP objectClass for roles.'), cfg.StrOpt('role_id_attribute', default='cn', help='LDAP attribute mapped to role id.'), cfg.StrOpt('role_name_attribute', default='ou', help='LDAP attribute mapped to role name.'), cfg.StrOpt('role_member_attribute', default='roleOccupant', help='LDAP attribute mapped to role membership.'), cfg.ListOpt('role_attribute_ignore', default=[], help='List of attributes stripped off the role on ' 'update.'), cfg.BoolOpt('role_allow_create', default=True, help='Allow role creation in LDAP backend.'), cfg.BoolOpt('role_allow_update', default=True, help='Allow role update in LDAP backend.'), cfg.BoolOpt('role_allow_delete', default=True, help='Allow role deletion in LDAP backend.'), cfg.ListOpt('role_additional_attribute_mapping', default=[], help='Additional attribute mappings for roles. Attribute ' 'mapping format is :, where ' 'ldap_attr is the attribute in the LDAP entry and ' 'user_attr is the Identity API attribute.'), cfg.StrOpt('group_tree_dn', default=None, help='Search base for groups.'), cfg.StrOpt('group_filter', default=None, help='LDAP search filter for groups.'), cfg.StrOpt('group_objectclass', default='groupOfNames', help='LDAP objectClass for groups.'), cfg.StrOpt('group_id_attribute', default='cn', help='LDAP attribute mapped to group id.'), cfg.StrOpt('group_name_attribute', default='ou', help='LDAP attribute mapped to group name.'), cfg.StrOpt('group_member_attribute', default='member', help='LDAP attribute mapped to show group membership.'), cfg.StrOpt('group_desc_attribute', default='description', help='LDAP attribute mapped to group description.'), cfg.ListOpt('group_attribute_ignore', default=[], help='List of attributes stripped off the group on ' 'update.'), cfg.BoolOpt('group_allow_create', default=True, help='Allow group creation in LDAP backend.'), cfg.BoolOpt('group_allow_update', default=True, help='Allow group update in LDAP backend.'), cfg.BoolOpt('group_allow_delete', default=True, help='Allow group deletion in LDAP backend.'), cfg.ListOpt('group_additional_attribute_mapping', default=[], help='Additional attribute mappings for groups. Attribute ' 'mapping format is :, where ' 'ldap_attr is the attribute in the LDAP entry and ' 'user_attr is the Identity API attribute.'), cfg.StrOpt('tls_cacertfile', default=None, help='CA certificate file path for communicating with ' 'LDAP servers.'), cfg.StrOpt('tls_cacertdir', default=None, help='CA certificate directory path for communicating with ' 'LDAP servers.'), cfg.BoolOpt('use_tls', default=False, help='Enable TLS for communicating with LDAP servers.'), cfg.StrOpt('tls_req_cert', default='demand', help='valid options for tls_req_cert are demand, never, ' 'and allow.')], 'auth': [ cfg.ListOpt('methods', default=_DEFAULT_AUTH_METHODS, help='Default auth methods.'), cfg.StrOpt('password', default='keystone.auth.plugins.password.Password', help='The password auth plugin module.'), cfg.StrOpt('token', default='keystone.auth.plugins.token.Token', help='The token auth plugin module.'), #deals with REMOTE_USER authentication cfg.StrOpt('external', default='keystone.auth.plugins.external.DefaultDomain', help='The external (REMOTE_USER) auth plugin module.')], 'paste_deploy': [ cfg.StrOpt('config_file', default='keystone-paste.ini', help='Name of the paste configuration file that defines ' 'the available pipelines.')], 'memcache': [ cfg.ListOpt('servers', default=['localhost:11211'], help='Memcache servers in the format of "host:port"'), cfg.IntOpt('max_compare_and_set_retry', default=16, help='Number of compare-and-set attempts to make when ' 'using compare-and-set in the token memcache back ' 'end.')], 'catalog': [ cfg.StrOpt('template_file', default='default_catalog.templates', help='Catalog template file name for use with the ' 'template catalog backend.'), cfg.StrOpt('driver', default='keystone.catalog.backends.sql.Catalog', help='Keystone catalog backend driver.'), cfg.IntOpt('list_limit', default=None, help='Maximum number of entities that will be returned ' 'in a catalog collection.')], 'kvs': [ cfg.ListOpt('backends', default=[], help='Extra dogpile.cache backend modules to register ' 'with the dogpile.cache library.'), cfg.StrOpt('config_prefix', default='keystone.kvs', help='Prefix for building the configuration dictionary ' 'for the KVS region. This should not need to be ' 'changed unless there is another dogpile.cache ' 'region with the same configuration name.'), cfg.BoolOpt('enable_key_mangler', default=True, help='Toggle to disable using a key-mangling function ' 'to ensure fixed length keys. This is toggle-able ' 'for debugging purposes, it is highly recommended ' 'to always leave this set to True.'), cfg.IntOpt('default_lock_timeout', default=5, help='Default lock timeout for distributed locking.')]} CONF = cfg.CONF def setup_authentication(conf=None): # register any non-default auth methods here (used by extensions, etc) if conf is None: conf = CONF for method_name in conf.auth.methods: if method_name not in _DEFAULT_AUTH_METHODS: conf.register_opt(cfg.StrOpt(method_name), group='auth') def configure(conf=None): if conf is None: conf = CONF conf.register_cli_opt( cfg.BoolOpt('standard-threads', default=False, help='Do not monkey-patch threading system modules.')) conf.register_cli_opt( cfg.StrOpt('pydev-debug-host', default=None, help='Host to connect to for remote debugger.')) conf.register_cli_opt( cfg.IntOpt('pydev-debug-port', default=None, help='Port to connect to for remote debugger.')) for section in FILE_OPTIONS: for option in FILE_OPTIONS[section]: if section: conf.register_opt(option, group=section) else: conf.register_opt(option) # register any non-default auth methods here (used by extensions, etc) setup_authentication(conf) def list_opts(): """Return a list of oslo.config options available in Keystone. The returned list includes all oslo.config options which are registered as the "FILE_OPTIONS" in keystone.common.config. This list will not include the options from the oslo-incubator library or any options registered dynamically at run time. Each object in the list is a two element tuple. The first element of each tuple is the name of the group under which the list of options in the second element will be registered. A group name of None corresponds to the [DEFAULT] group in config files. This function is also discoverable via the 'oslo.config.opts' entry point under the 'keystone.config.opts' namespace. The purpose of this is to allow tools like the Oslo sample config file generator to discover the options exposed to users by this library. :returns: a list of (group_name, opts) tuples """ return FILE_OPTIONS.items() keystone-2014.1/keystone/common/models.py0000664000175400017540000000632612323716267021606 0ustar jenkinsjenkins00000000000000# Copyright (C) 2011 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. """Base model for keystone internal services Unless marked otherwise, all fields are strings. """ class Model(dict): """Base model class.""" def __hash__(self): return self['id'].__hash__() @property def known_keys(cls): return cls.required_keys + cls.optional_keys class Token(Model): """Token object. Required keys: id expires (datetime) Optional keys: user tenant metadata trust_id """ required_keys = ('id', 'expires') optional_keys = ('extra',) class Service(Model): """Service object. Required keys: id type name Optional keys: """ required_keys = ('id', 'type', 'name') optional_keys = tuple() class Endpoint(Model): """Endpoint object Required keys: id region service_id Optional keys: internalurl publicurl adminurl """ required_keys = ('id', 'region', 'service_id') optional_keys = ('internalurl', 'publicurl', 'adminurl') class User(Model): """User object. Required keys: id name domain_id Optional keys: password description email enabled (bool, default True) default_project_id """ required_keys = ('id', 'name', 'domain_id') optional_keys = ('password', 'description', 'email', 'enabled', 'default_project_id') class Group(Model): """Group object. Required keys: id name domain_id Optional keys: description """ required_keys = ('id', 'name', 'domain_id') optional_keys = ('description',) class Project(Model): """Project object. Required keys: id name domain_id Optional Keys: description enabled (bool, default True) """ required_keys = ('id', 'name', 'domain_id') optional_keys = ('description', 'enabled') class Role(Model): """Role object. Required keys: id name """ required_keys = ('id', 'name') optional_keys = tuple() class Trust(Model): """Trust object. Required keys: id trustor_user_id trustee_user_id project_id """ required_keys = ('id', 'trustor_user_id', 'trustee_user_id', 'project_id') optional_keys = ('expires_at',) class Domain(Model): """Domain object. Required keys: id name Optional keys: description enabled (bool, default True) """ required_keys = ('id', 'name') optional_keys = ('description', 'enabled') keystone-2014.1/keystone/common/router.py0000664000175400017540000000372412323716267021642 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import wsgi class Router(wsgi.ComposableRouter): def __init__(self, controller, collection_key, key): self.controller = controller self.key = key self.collection_key = collection_key def add_routes(self, mapper): collection_path = '/%(collection_key)s' % { 'collection_key': self.collection_key} entity_path = '/%(collection_key)s/{%(key)s_id}' % { 'collection_key': self.collection_key, 'key': self.key} mapper.connect( collection_path, controller=self.controller, action='create_%s' % self.key, conditions=dict(method=['POST'])) mapper.connect( collection_path, controller=self.controller, action='list_%s' % self.collection_key, conditions=dict(method=['GET'])) mapper.connect( entity_path, controller=self.controller, action='get_%s' % self.key, conditions=dict(method=['GET'])) mapper.connect( entity_path, controller=self.controller, action='update_%s' % self.key, conditions=dict(method=['PATCH'])) mapper.connect( entity_path, controller=self.controller, action='delete_%s' % self.key, conditions=dict(method=['DELETE'])) keystone-2014.1/keystone/common/openssl.py0000664000175400017540000002572012323716267022005 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. # import os from keystone.common import environment from keystone.common import utils from keystone import config from keystone.openstack.common import log LOG = log.getLogger(__name__) CONF = config.CONF PUBLIC_DIR_PERMS = 0o755 # -rwxr-xr-x PRIVATE_DIR_PERMS = 0o750 # -rwxr-x--- PUBLIC_FILE_PERMS = 0o644 # -rw-r--r-- PRIVATE_FILE_PERMS = 0o640 # -rw-r----- def file_exists(file_path): return os.path.exists(file_path) class BaseCertificateConfigure(object): """Create a certificate signing environment. This is based on a config section and reasonable OpenSSL defaults. """ def __init__(self, conf_obj, keystone_user, keystone_group, **kwargs): self.conf_dir = os.path.dirname(conf_obj.ca_certs) self.use_keystone_user = keystone_user self.use_keystone_group = keystone_group self.ssl_config_file_name = os.path.join(self.conf_dir, "openssl.conf") self.request_file_name = os.path.join(self.conf_dir, "req.pem") self.ssl_dictionary = {'conf_dir': self.conf_dir, 'ca_cert': conf_obj.ca_certs, 'default_md': 'default', 'ssl_config': self.ssl_config_file_name, 'ca_private_key': conf_obj.ca_key, 'request_file': self.request_file_name, 'signing_key': conf_obj.keyfile, 'signing_cert': conf_obj.certfile, 'key_size': int(conf_obj.key_size), 'valid_days': int(conf_obj.valid_days), 'cert_subject': conf_obj.cert_subject} try: # OpenSSL 1.0 and newer support default_md = default, olders do not openssl_ver = environment.subprocess.Popen( ['openssl', 'version'], stdout=environment.subprocess.PIPE).stdout.read() if "OpenSSL 0." in openssl_ver: self.ssl_dictionary['default_md'] = 'sha1' except OSError: LOG.warn('Failed to invoke ``openssl version``, ' 'assuming is v1.0 or newer') self.ssl_dictionary.update(kwargs) def exec_command(self, command): to_exec = [] for cmd_part in command: to_exec.append(cmd_part % self.ssl_dictionary) LOG.info(' '.join(to_exec)) environment.subprocess.check_call(to_exec) def build_ssl_config_file(self): utils.make_dirs(os.path.dirname(self.ssl_config_file_name), mode=PUBLIC_DIR_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) if not file_exists(self.ssl_config_file_name): ssl_config_file = open(self.ssl_config_file_name, 'w') ssl_config_file.write(self.sslconfig % self.ssl_dictionary) ssl_config_file.close() utils.set_permissions(self.ssl_config_file_name, mode=PRIVATE_FILE_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) index_file_name = os.path.join(self.conf_dir, 'index.txt') if not file_exists(index_file_name): index_file = open(index_file_name, 'w') index_file.write('') index_file.close() utils.set_permissions(index_file_name, mode=PRIVATE_FILE_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) serial_file_name = os.path.join(self.conf_dir, 'serial') if not file_exists(serial_file_name): index_file = open(serial_file_name, 'w') index_file.write('01') index_file.close() utils.set_permissions(serial_file_name, mode=PRIVATE_FILE_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) def build_ca_cert(self): ca_key_file = self.ssl_dictionary['ca_private_key'] utils.make_dirs(os.path.dirname(ca_key_file), mode=PRIVATE_DIR_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) if not file_exists(ca_key_file): self.exec_command(['openssl', 'genrsa', '-out', '%(ca_private_key)s', '%(key_size)d']) utils.set_permissions(ca_key_file, mode=PRIVATE_FILE_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) ca_cert = self.ssl_dictionary['ca_cert'] utils.make_dirs(os.path.dirname(ca_cert), mode=PUBLIC_DIR_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) if not file_exists(ca_cert): self.exec_command(['openssl', 'req', '-new', '-x509', '-extensions', 'v3_ca', '-key', '%(ca_private_key)s', '-out', '%(ca_cert)s', '-days', '%(valid_days)d', '-config', '%(ssl_config)s', '-subj', '%(cert_subject)s']) utils.set_permissions(ca_cert, mode=PUBLIC_FILE_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) def build_private_key(self): signing_keyfile = self.ssl_dictionary['signing_key'] utils.make_dirs(os.path.dirname(signing_keyfile), mode=PRIVATE_DIR_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) if not file_exists(signing_keyfile): self.exec_command(['openssl', 'genrsa', '-out', '%(signing_key)s', '%(key_size)d']) utils.set_permissions(signing_keyfile, mode=PRIVATE_FILE_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) def build_signing_cert(self): signing_cert = self.ssl_dictionary['signing_cert'] utils.make_dirs(os.path.dirname(signing_cert), mode=PUBLIC_DIR_PERMS, user=self.use_keystone_user, group=self.use_keystone_group, log=LOG) if not file_exists(signing_cert): self.exec_command(['openssl', 'req', '-key', '%(signing_key)s', '-new', '-out', '%(request_file)s', '-config', '%(ssl_config)s', '-subj', '%(cert_subject)s']) self.exec_command(['openssl', 'ca', '-batch', '-out', '%(signing_cert)s', '-config', '%(ssl_config)s', '-days', '%(valid_days)dd', '-cert', '%(ca_cert)s', '-keyfile', '%(ca_private_key)s', '-infiles', '%(request_file)s']) def run(self): self.build_ssl_config_file() self.build_ca_cert() self.build_private_key() self.build_signing_cert() class ConfigurePKI(BaseCertificateConfigure): """Generate files for PKI signing using OpenSSL. Signed tokens require a private key and signing certificate which itself must be signed by a CA. This class generates them with workable defaults if each of the files are not present """ def __init__(self, keystone_user, keystone_group): super(ConfigurePKI, self).__init__(CONF.signing, keystone_user, keystone_group) class ConfigureSSL(BaseCertificateConfigure): """Generate files for HTTPS using OpenSSL. Creates a public/private key and certificates. If a CA is not given one will be generated using provided arguments. """ def __init__(self, keystone_user, keystone_group): super(ConfigureSSL, self).__init__(CONF.ssl, keystone_user, keystone_group) BaseCertificateConfigure.sslconfig = """ # OpenSSL configuration file. # # Establish working directory. dir = %(conf_dir)s [ ca ] default_ca = CA_default [ CA_default ] new_certs_dir = $dir serial = $dir/serial database = $dir/index.txt default_days = 365 default_md = %(default_md)s preserve = no email_in_dn = no nameopt = default_ca certopt = default_ca policy = policy_anything x509_extensions = usr_cert unique_subject = no [ policy_anything ] countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] default_bits = 2048 # Size of keys default_keyfile = key.pem # name of generated keys string_mask = utf8only # permitted characters distinguished_name = req_distinguished_name req_extensions = v3_req x509_extensions = v3_ca [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (city, district) 0.organizationName = Organization Name (company) organizationalUnitName = Organizational Unit Name (department, division) commonName = Common Name (hostname, IP, or your name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [ v3_ca ] basicConstraints = CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ usr_cert ] basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always """ keystone-2014.1/keystone/common/controller.py0000664000175400017540000006450012323716272022500 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import functools import uuid from keystone.common import authorization from keystone.common import dependency from keystone.common import driver_hints from keystone.common import utils from keystone.common import wsgi from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log LOG = log.getLogger(__name__) CONF = config.CONF def v2_deprecated(f): """No-op decorator in preparation for deprecating Identity API v2. This is a placeholder for the pending deprecation of v2. The implementation of this decorator can be replaced with:: from keystone.openstack.common import versionutils v2_deprecated = versionutils.deprecated( what='v2 API', as_of=versionutils.deprecated.JUNO, in_favor_of='v3 API') """ return f def _build_policy_check_credentials(self, action, context, kwargs): LOG.debug(_('RBAC: Authorizing %(action)s(%(kwargs)s)'), { 'action': action, 'kwargs': ', '.join(['%s=%s' % (k, kwargs[k]) for k in kwargs])}) # see if auth context has already been created. If so use it. if ('environment' in context and authorization.AUTH_CONTEXT_ENV in context['environment']): LOG.debug(_('RBAC: using auth context from the request environment')) return context['environment'].get(authorization.AUTH_CONTEXT_ENV) # now build the auth context from the incoming auth token try: LOG.debug(_('RBAC: building auth context from the incoming ' 'auth token')) # TODO(ayoung): These two functions return the token in different # formats. However, the call # to get_token hits the caching layer, and does not validate the # token. This should be reduced to one call if not CONF.token.revoke_by_id: self.token_api.token_provider_api.validate_token( context['token_id']) token_ref = self.token_api.get_token(context['token_id']) except exception.TokenNotFound: LOG.warning(_('RBAC: Invalid token')) raise exception.Unauthorized() # NOTE(jamielennox): whilst this maybe shouldn't be within this function # it would otherwise need to reload the token_ref from backing store. wsgi.validate_token_bind(context, token_ref) auth_context = authorization.token_to_auth_context(token_ref['token_data']) return auth_context def protected(callback=None): """Wraps API calls with role based access controls (RBAC). This handles both the protection of the API parameters as well as any target entities for single-entity API calls. More complex API calls (for example that deal with several different entities) should pass in a callback function, that will be subsequently called to check protection for these multiple entities. This callback function should gather the appropriate entities needed and then call check_proetction() in the V3Controller class. """ def wrapper(f): @functools.wraps(f) def inner(self, context, *args, **kwargs): if 'is_admin' in context and context['is_admin']: LOG.warning(_('RBAC: Bypassing authorization')) elif callback is not None: prep_info = {'f_name': f.__name__, 'input_attr': kwargs} callback(self, context, prep_info, *args, **kwargs) else: action = 'identity:%s' % f.__name__ creds = _build_policy_check_credentials(self, action, context, kwargs) policy_dict = {} # Check to see if we need to include the target entity in our # policy checks. We deduce this by seeing if the class has # specified a get_member() method and that kwargs contains the # appropriate entity id. if (hasattr(self, 'get_member_from_driver') and self.get_member_from_driver is not None): key = '%s_id' % self.member_name if key in kwargs: ref = self.get_member_from_driver(kwargs[key]) policy_dict['target'] = {self.member_name: ref} # TODO(henry-nash): Move this entire code to a member # method inside v3 Auth if context.get('subject_token_id') is not None: token_ref = self.token_api.get_token( context['subject_token_id']) policy_dict.setdefault('target', {}) policy_dict['target'].setdefault(self.member_name, {}) policy_dict['target'][self.member_name]['user_id'] = ( token_ref['user_id']) if 'domain' in token_ref['user']: policy_dict['target'][self.member_name].setdefault( 'user', {}) policy_dict['target'][self.member_name][ 'user'].setdefault('domain', {}) policy_dict['target'][self.member_name]['user'][ 'domain']['id'] = ( token_ref['user']['domain']['id']) # Add in the kwargs, which means that any entity provided as a # parameter for calls like create and update will be included. policy_dict.update(kwargs) self.policy_api.enforce(creds, action, authorization.flatten(policy_dict)) LOG.debug(_('RBAC: Authorization granted')) return f(self, context, *args, **kwargs) return inner return wrapper def filterprotected(*filters): """Wraps filtered API calls with role based access controls (RBAC).""" def _filterprotected(f): @functools.wraps(f) def wrapper(self, context, **kwargs): if not context['is_admin']: action = 'identity:%s' % f.__name__ creds = _build_policy_check_credentials(self, action, context, kwargs) # Now, build the target dict for policy check. We include: # # - Any query filter parameters # - Data from the main url (which will be in the kwargs # parameter) and would typically include the prime key # of a get/update/delete call # # First any query filter parameters target = dict() if filters: for item in filters: if item in context['query_string']: target[item] = context['query_string'][item] LOG.debug(_('RBAC: Adding query filter params (%s)'), ( ', '.join(['%s=%s' % (item, target[item]) for item in target]))) # Now any formal url parameters for key in kwargs: target[key] = kwargs[key] self.policy_api.enforce(creds, action, authorization.flatten(target)) LOG.debug(_('RBAC: Authorization granted')) else: LOG.warning(_('RBAC: Bypassing authorization')) return f(self, context, filters, **kwargs) return wrapper return _filterprotected class V2Controller(wsgi.Application): """Base controller class for Identity API v2.""" def _normalize_domain_id(self, context, ref): """Fill in domain_id since v2 calls are not domain-aware. This will overwrite any domain_id that was inadvertently specified in the v2 call. """ ref['domain_id'] = CONF.identity.default_domain_id return ref @staticmethod def filter_domain_id(ref): """Remove domain_id since v2 calls are not domain-aware.""" ref.pop('domain_id', None) return ref @staticmethod def normalize_username_in_response(ref): """Adds username to outgoing user refs to match the v2 spec. Internally we use `name` to represent a user's name. The v2 spec requires the use of `username` instead. """ if 'username' not in ref and 'name' in ref: ref['username'] = ref['name'] return ref @staticmethod def normalize_username_in_request(ref): """Adds name in incoming user refs to match the v2 spec. Internally we use `name` to represent a user's name. The v2 spec requires the use of `username` instead. """ if 'name' not in ref and 'username' in ref: ref['name'] = ref.pop('username') return ref @staticmethod def v3_to_v2_user(ref): """Convert a user_ref from v3 to v2 compatible. * v2.0 users are not domain aware, and should have domain_id removed * v2.0 users expect the use of tenantId instead of default_project_id * v2.0 users have a username attribute This method should only be applied to user_refs being returned from the v2.0 controller(s). If ref is a list type, we will iterate through each element and do the conversion. """ def _format_default_project_id(ref): """Convert default_project_id to tenantId for v2 calls.""" default_project_id = ref.pop('default_project_id', None) if default_project_id is not None: ref['tenantId'] = default_project_id elif 'tenantId' in ref: # NOTE(morganfainberg): To avoid v2.0 confusion if somehow a # tenantId property sneaks its way into the extra blob on the # user, we remove it here. If default_project_id is set, we # would override it in either case. del ref['tenantId'] def _normalize_and_filter_user_properties(ref): """Run through the various filter/normalization methods.""" _format_default_project_id(ref) V2Controller.filter_domain_id(ref) V2Controller.normalize_username_in_response(ref) return ref if isinstance(ref, dict): return _normalize_and_filter_user_properties(ref) elif isinstance(ref, list): return [_normalize_and_filter_user_properties(x) for x in ref] else: raise ValueError(_('Expected dict or list: %s') % type(ref)) @dependency.requires('policy_api', 'token_api') class V3Controller(wsgi.Application): """Base controller class for Identity API v3. Child classes should set the ``collection_name`` and ``member_name`` class attributes, representing the collection of entities they are exposing to the API. This is required for supporting self-referential links, pagination, etc. Class parameters: * `_mutable_parameters` - set of parameters that can be changed by users. Usually used by cls.check_immutable_params() * `_public_parameters` - set of parameters that are exposed to the user. Usually used by cls.filter_params() """ collection_name = 'entities' member_name = 'entity' get_member_from_driver = None @classmethod def base_url(cls, context, path=None): endpoint = super(V3Controller, cls).base_url(context, 'public') if not path: path = cls.collection_name return '%s/%s/%s' % (endpoint, 'v3', path.lstrip('/')) @classmethod def _add_self_referential_link(cls, context, ref): ref.setdefault('links', {}) ref['links']['self'] = cls.base_url(context) + '/' + ref['id'] @classmethod def wrap_member(cls, context, ref): cls._add_self_referential_link(context, ref) return {cls.member_name: ref} @classmethod def wrap_collection(cls, context, refs, hints=None): """Wrap a collection, checking for filtering and pagination. Returns the wrapped collection, which includes: - Executing any filtering not already carried out - Truncate to a set limit if necessary - Adds 'self' links in every member - Adds 'next', 'self' and 'prev' links for the whole collection. :param context: the current context, containing the original url path and query string :param refs: the list of members of the collection :param hints: list hints, containing any relevant filters and limit. Any filters already satisfied by managers will have been removed """ # Check if there are any filters in hints that were not # handled by the drivers. The driver will not have paginated or # limited the output if it found there were filters it was unable to # handle. if hints is not None: refs = cls.filter_by_attributes(refs, hints) list_limited, refs = cls.limit(refs, hints) for ref in refs: cls.wrap_member(context, ref) container = {cls.collection_name: refs} container['links'] = { 'next': None, 'self': cls.base_url(context, path=context['path']), 'previous': None} if list_limited: container['truncated'] = True return container @classmethod def limit(cls, refs, hints): """Limits a list of entities. The underlying driver layer may have already truncated the collection for us, but in case it was unable to handle truncation we check here. :param refs: the list of members of the collection :param hints: hints, containing, among other things, the limit requested :returns: boolean indicating whether the list was truncated, as well as the list of (truncated if necessary) entities. """ NOT_LIMITED = False LIMITED = True if hints is None or hints.get_limit() is None: # No truncation was requested return NOT_LIMITED, refs list_limit = hints.get_limit() if list_limit.get('truncated', False): # The driver did truncate the list return LIMITED, refs if len(refs) > list_limit['limit']: # The driver layer wasn't able to truncate it for us, so we must # do it here return LIMITED, refs[:list_limit['limit']] return NOT_LIMITED, refs @classmethod def filter_by_attributes(cls, refs, hints): """Filters a list of references by filter values.""" def _attr_match(ref_attr, val_attr): """Matches attributes allowing for booleans as strings. We test explicitly for a value that defines it as 'False', which also means that the existence of the attribute with no value implies 'True' """ if type(ref_attr) is bool: return ref_attr == utils.attr_as_boolean(val_attr) else: return ref_attr == val_attr def _inexact_attr_match(filter, ref): """Applies an inexact filter to a result dict. :param filter: the filter in question :param ref: the dict to check :returns True if there is a match """ comparator = filter['comparator'] key = filter['name'] if key in ref: filter_value = filter['value'] target_value = ref[key] if not filter['case_sensitive']: # We only support inexact filters on strings so # it's OK to use lower() filter_value = filter_value.lower() target_value = target_value.lower() if comparator == 'contains': return (filter_value in target_value) elif comparator == 'startswith': return target_value.startswith(filter_value) elif comparator == 'endswith': return target_value.endswith(filter_value) else: # We silently ignore unsupported filters return True return False for filter in hints.filters(): if filter['comparator'] == 'equals': attr = filter['name'] value = filter['value'] refs = [r for r in refs if _attr_match( authorization.flatten(r).get(attr), value)] else: # It might be an inexact filter refs = [r for r in refs if _inexact_attr_match( filter, r)] return refs @classmethod def build_driver_hints(cls, context, supported_filters): """Build list hints based on the context query string. :param context: contains the query_string from which any list hints can be extracted :param supported_filters: list of filters supported, so ignore any keys in query_dict that are not in this list. """ query_dict = context['query_string'] hints = driver_hints.Hints() if query_dict is None: return hints for key in query_dict: # Check if this is an exact filter if supported_filters is None or key in supported_filters: hints.add_filter(key, query_dict[key]) continue # Check if it is an inexact filter for valid_key in supported_filters: # See if this entry in query_dict matches a known key with an # inexact suffix added. If it doesn't match, then that just # means that there is no inexact filter for that key in this # query. if not key.startswith(valid_key + '__'): continue base_key, comparator = key.split('__', 1) # We map the query-style inexact of, for example: # # {'email__contains', 'myISP'} # # into a list directive add filter call parameters of: # # name = 'email' # value = 'myISP' # comparator = 'contains' # case_sensitive = True case_sensitive = True if comparator.startswith('i'): case_sensitive = False comparator = comparator[1:] hints.add_filter(base_key, query_dict[key], comparator=comparator, case_sensitive=case_sensitive) # NOTE(henry-nash): If we were to support pagination, we would pull any # pagination directives out of the query_dict here, and add them into # the hints list. return hints def _require_matching_id(self, value, ref): """Ensures the value matches the reference's ID, if any.""" if 'id' in ref and ref['id'] != value: raise exception.ValidationError('Cannot change ID') def _require_matching_domain_id(self, ref_id, ref, get_member): """Ensure the current domain ID matches the reference one, if any. Provided we want domain IDs to be immutable, check whether any domain_id specified in the ref dictionary matches the existing domain_id for this entity. :param ref_id: the ID of the entity :param ref: the dictionary of new values proposed for this entity :param get_member: The member function to call to get the current entity :raises: :class:`keystone.exception.ValidationError` """ # TODO(henry-nash): It might be safer and more efficient to do this # check in the managers affected, so look to migrate this check to # there in the future. if CONF.domain_id_immutable and 'domain_id' in ref: existing_ref = get_member(ref_id) if ref['domain_id'] != existing_ref['domain_id']: raise exception.ValidationError(_('Cannot change Domain ID')) def _assign_unique_id(self, ref): """Generates and assigns a unique identifer to a reference.""" ref = ref.copy() ref['id'] = uuid.uuid4().hex return ref def _get_domain_id_for_request(self, context): """Get the domain_id for a v3 call.""" if context['is_admin']: return CONF.identity.default_domain_id # Fish the domain_id out of the token # # We could make this more efficient by loading the domain_id # into the context in the wrapper function above (since # this version of normalize_domain will only be called inside # a v3 protected call). However, this optimization is probably not # worth the duplication of state try: token_ref = self.token_api.get_token(context['token_id']) except exception.TokenNotFound: LOG.warning(_('Invalid token in _get_domain_id_for_request')) raise exception.Unauthorized() if 'domain' in token_ref: return token_ref['domain']['id'] else: return CONF.identity.default_domain_id def _normalize_domain_id(self, context, ref): """Fill in domain_id if not specified in a v3 call.""" if 'domain_id' not in ref: ref['domain_id'] = self._get_domain_id_for_request(context) return ref @staticmethod def filter_domain_id(ref): """Override v2 filter to let domain_id out for v3 calls.""" return ref def check_protection(self, context, prep_info, target_attr=None): """Provide call protection for complex target attributes. As well as including the standard parameters from the original API call (which is passed in prep_info), this call will add in any additional entities or attributes (passed in target_attr), so that they can be referenced by policy rules. """ if 'is_admin' in context and context['is_admin']: LOG.warning(_('RBAC: Bypassing authorization')) else: action = 'identity:%s' % prep_info['f_name'] # TODO(henry-nash) need to log the target attributes as well creds = _build_policy_check_credentials(self, action, context, prep_info['input_attr']) # Build the dict the policy engine will check against from both the # parameters passed into the call we are protecting (which was # stored in the prep_info by protected()), plus the target # attributes provided. policy_dict = {} if target_attr: policy_dict = {'target': target_attr} policy_dict.update(prep_info['input_attr']) self.policy_api.enforce(creds, action, authorization.flatten(policy_dict)) LOG.debug(_('RBAC: Authorization granted')) @classmethod def check_immutable_params(cls, ref): """Raise exception when disallowed parameter is in ref. Check whether the ref dictionary representing a request has only mutable parameters included. If not, raise an exception. This method checks only root-level keys from a ref dictionary. :param ref: a dictionary representing deserialized request to be stored :raises: :class:`keystone.exception.ImmutableAttributeError` """ ref_keys = set(ref.keys()) blocked_keys = ref_keys.difference(cls._mutable_parameters) if not blocked_keys: #No immutable parameters changed return exception_args = {'target': cls.__name__, 'attribute': blocked_keys.pop()} raise exception.ImmutableAttributeError(**exception_args) @classmethod def check_required_params(cls, ref): """Raise exception when required parameter is not in ref. Check whether the ref dictionary representing a request has the required parameters to fulfill the request. If not, raise an exception. This method checks only root-level keys from a ref dictionary. :param ref: a dictionary representing deserialized request to be stored :raises: :class:`keystone.exception.ValidationError` """ ref_keys = set(ref.keys()) missing_args = [] for required in cls._required_parameters: if required not in ref_keys: missing_args.append(required) if len(missing_args) > 0: exception_args = {'target': cls.__name__, 'attribute': missing_args.pop()} raise exception.ValidationError(**exception_args) else: return @classmethod def filter_params(cls, ref): """Remove unspecified parameters from the dictionary. This function removes unspecified parameters from the dictionary. See check_immutable_parameters for corresponding function that raises exceptions. This method checks only root-level keys from a ref dictionary. :param ref: a dictionary representing deserialized response to be serialized """ ref_keys = set(ref.keys()) blocked_keys = ref_keys - cls._public_parameters for blocked_param in blocked_keys: del ref[blocked_param] return ref keystone-2014.1/keystone/common/kvs/0000775000175400017540000000000012323716511020535 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/kvs/core.py0000664000175400017540000004202412323716272022045 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, 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. import contextlib import threading import time import weakref from dogpile.cache import api from dogpile.cache import proxy from dogpile.cache import region from dogpile.cache import util as dogpile_util from dogpile.core import nameregistry import six from keystone.common import config from keystone import exception from keystone.openstack.common.gettextutils import _ # flake8: noqa from keystone.openstack.common import importutils from keystone.openstack.common import log __all__ = ['KeyValueStore', 'KeyValueStoreLock', 'LockTimeout', 'get_key_value_store'] BACKENDS_REGISTERED = False CONF = config.CONF KEY_VALUE_STORE_REGISTRY = weakref.WeakValueDictionary() LOCK_WINDOW = 1 LOG = log.getLogger(__name__) NO_VALUE = api.NO_VALUE def _register_backends(): # NOTE(morganfainberg): This function exists to ensure we do not try and # register the backends prior to the configuration object being fully # available. We also need to ensure we do not register a given backend # more than one time. All backends will be prefixed with openstack.kvs # as the "short" name to reference them for configuration purposes. This # function is used in addition to the pre-registered backends in the # __init__ file for the KVS system. global BACKENDS_REGISTERED if not BACKENDS_REGISTERED: prefix = 'openstack.kvs.%s' for backend in CONF.kvs.backends: module, cls = backend.rsplit('.', 1) backend_name = prefix % cls LOG.debug(_('Registering Dogpile Backend %(backend_path)s as ' '%(backend_name)s'), {'backend_path': backend, 'backend_name': backend_name}) region.register_backend(backend_name, module, cls) BACKENDS_REGISTERED = True class LockTimeout(exception.UnexpectedError): debug_message_format = _('Lock Timeout occurred for key, %(target)s') class KeyValueStore(object): """Basic KVS manager object to support Keystone Key-Value-Store systems. This manager also supports the concept of locking a given key resource to allow for a guaranteed atomic transaction to the backend. """ def __init__(self, kvs_region): self.locking = True self._lock_timeout = 0 self._region = kvs_region self._security_strategy = None self._secret_key = None self._lock_registry = nameregistry.NameRegistry(self._create_mutex) def configure(self, backing_store, key_mangler=None, proxy_list=None, locking=True, **region_config_args): """Configure the KeyValueStore instance. :param backing_store: dogpile.cache short name of the region backend :param key_mangler: key_mangler function :param proxy_list: list of proxy classes to apply to the region :param locking: boolean that allows disabling of locking mechanism for this instantiation :param region_config_args: key-word args passed to the dogpile.cache backend for configuration :return: """ if 'backend' in self._region.__dict__: # NOTE(morganfainberg): It is a bad idea to reconfigure a backend, # there are a lot of pitfalls and potential memory leaks that could # occur. By far the best approach is to re-create the KVS object # with the new configuration. raise RuntimeError(_('KVS region %s is already configured. ' 'Cannot reconfigure.') % self._region.name) self.locking = locking self._lock_timeout = region_config_args.pop( 'lock_timeout', CONF.kvs.default_lock_timeout) self._configure_region(backing_store, **region_config_args) self._set_key_mangler(key_mangler) self._apply_region_proxy(proxy_list) def _apply_region_proxy(self, proxy_list): if isinstance(proxy_list, list): proxies = [] for item in proxy_list: if isinstance(item, str): LOG.debug(_('Importing class %s as KVS proxy.'), item) pxy = importutils.import_class(item) else: pxy = item if issubclass(pxy, proxy.ProxyBackend): proxies.append(pxy) else: LOG.warning(_('%s is not a dogpile.proxy.ProxyBackend'), pxy.__name__) for proxy_cls in reversed(proxies): LOG.info(_('Adding proxy \'%(proxy)s\' to KVS %(name)s.'), {'proxy': proxy_cls.__name__, 'name': self._region.name}) self._region.wrap(proxy_cls) def _assert_configured(self): if'backend' not in self._region.__dict__: raise exception.UnexpectedError(_('Key Value Store not ' 'configured: %s'), self._region.name) def _set_keymangler_on_backend(self, key_mangler): try: self._region.backend.key_mangler = key_mangler except Exception as e: # NOTE(morganfainberg): The setting of the key_mangler on the # backend is used to allow the backend to # calculate a hashed key value as needed. Not all backends # require the ability to calculate hashed keys. If the # backend does not support/require this feature log a # debug line and move on otherwise raise the proper exception. # Support of the feature is implied by the existence of the # 'raw_no_expiry_keys' attribute. if not hasattr(self._region.backend, 'raw_no_expiry_keys'): LOG.debug(_('Non-expiring keys not supported/required by ' '%(region)s backend; unable to set ' 'key_mangler for backend: %(err)s'), {'region': self._region.name, 'err': e}) else: raise def _set_key_mangler(self, key_mangler): # Set the key_mangler that is appropriate for the given region being # configured here. The key_mangler function is called prior to storing # the value(s) in the backend. This is to help prevent collisions and # limit issues such as memcache's limited cache_key size. use_backend_key_mangler = getattr(self._region.backend, 'use_backend_key_mangler', False) if ((key_mangler is None or use_backend_key_mangler) and (self._region.backend.key_mangler is not None)): # NOTE(morganfainberg): Use the configured key_mangler as a first # choice. Second choice would be the key_mangler defined by the # backend itself. Finally, fall back to the defaults. The one # exception is if the backend defines `use_backend_key_mangler` # as True, which indicates the backend's key_mangler should be # the first choice. key_mangler = self._region.backend.key_mangler if CONF.kvs.enable_key_mangler: if key_mangler is not None: msg = _('Using %(func)s as KVS region %(name)s key_mangler') if callable(key_mangler): self._region.key_mangler = key_mangler LOG.info(msg, {'func': key_mangler.__name__, 'name': self._region.name}) else: # NOTE(morganfainberg): We failed to set the key_mangler, # we should error out here to ensure we aren't causing # key-length or collision issues. raise exception.ValidationError( _('`key_mangler` option must be a function reference')) else: LOG.info(_('Using default dogpile sha1_mangle_key as KVS ' 'region %s key_mangler'), self._region.name) # NOTE(morganfainberg): Sane 'default' keymangler is the # dogpile sha1_mangle_key function. This ensures that unless # explicitly changed, we mangle keys. This helps to limit # unintended cases of exceeding cache-key in backends such # as memcache. self._region.key_mangler = dogpile_util.sha1_mangle_key self._set_keymangler_on_backend(self._region.key_mangler) else: LOG.info(_('KVS region %s key_mangler disabled.'), self._region.name) self._set_keymangler_on_backend(None) def _configure_region(self, backend, **config_args): prefix = CONF.kvs.config_prefix conf_dict = {} conf_dict['%s.backend' % prefix] = backend if 'distributed_lock' not in config_args: config_args['distributed_lock'] = True config_args['lock_timeout'] = self._lock_timeout # NOTE(morganfainberg): To mitigate race conditions on comparing # the timeout and current time on the lock mutex, we are building # in a static 1 second overlap where the lock will still be valid # in the backend but not from the perspective of the context # manager. Since we must develop to the lowest-common-denominator # when it comes to the backends, memcache's cache store is not more # refined than 1 second, therefore we must build in at least a 1 # second overlap. `lock_timeout` of 0 means locks never expire. if config_args['lock_timeout'] > 0: config_args['lock_timeout'] += LOCK_WINDOW for argument, value in six.iteritems(config_args): arg_key = '.'.join([prefix, 'arguments', argument]) conf_dict[arg_key] = value LOG.debug(_('KVS region configuration for %(name)s: %(config)r'), {'name': self._region.name, 'config': conf_dict}) self._region.configure_from_config(conf_dict, '%s.' % prefix) def _mutex(self, key): return self._lock_registry.get(key) def _create_mutex(self, key): mutex = self._region.backend.get_mutex(key) if mutex is not None: return mutex else: return self._LockWrapper(lock_timeout=self._lock_timeout) class _LockWrapper(object): """weakref-capable threading.Lock wrapper.""" def __init__(self, lock_timeout): self.lock = threading.Lock() self.lock_timeout = lock_timeout def acquire(self, wait=True): return self.lock.acquire(wait) def release(self): self.lock.release() def get(self, key): """Get a single value from the KVS backend.""" self._assert_configured() value = self._region.get(key) if value is NO_VALUE: raise exception.NotFound(target=key) return value def get_multi(self, keys): """Get multiple values in a single call from the KVS backend.""" self._assert_configured() values = self._region.get_multi(keys) not_found = [] for index, key in enumerate(keys): if values[index] is NO_VALUE: not_found.append(key) if not_found: # NOTE(morganfainberg): If any of the multi-get values are non- # existent, we should raise a NotFound error to mimic the .get() # method's behavior. In all cases the internal dogpile NO_VALUE # should be masked from the consumer of the KeyValueStore. raise exception.NotFound(target=not_found) return values def set(self, key, value, lock=None): """Set a single value in the KVS backend.""" self._assert_configured() with self._action_with_lock(key, lock): self._region.set(key, value) def set_multi(self, mapping): """Set multiple key/value pairs in the KVS backend at once. Like delete_multi, this call does not serialize through the KeyValueStoreLock mechanism (locking cannot occur on more than one key in a given context without significant deadlock potential). """ self._assert_configured() self._region.set_multi(mapping) def delete(self, key, lock=None): """Delete a single key from the KVS backend. This method will raise NotFound if the key doesn't exist. The get and delete are done in a single transaction (via KeyValueStoreLock mechanism). """ self._assert_configured() with self._action_with_lock(key, lock): self.get(key) self._region.delete(key) def delete_multi(self, keys): """Delete multiple keys from the KVS backend in a single call. Like set_multi, this call does not serialize through the KeyValueStoreLock mechanism (locking cannot occur on more than one key in a given context without significant deadlock potential). """ self._assert_configured() self._region.delete_multi(keys) def get_lock(self, key): """Get a write lock on the KVS value referenced by `key`. The ability to get a context manager to pass into the set/delete methods allows for a single-transaction to occur while guaranteeing the backing store will not change between the start of the 'lock' and the end. Lock timeout is fixed to the KeyValueStore configured lock timeout. """ self._assert_configured() return KeyValueStoreLock(self._mutex(key), key, self.locking) @contextlib.contextmanager def _action_with_lock(self, key, lock=None): """Wrapper context manager to validate and handle the lock and lock timeout if passed in. """ if not isinstance(lock, KeyValueStoreLock): # NOTE(morganfainberg): Locking only matters if a lock is passed in # to this method. If lock isn't a KeyValueStoreLock, treat this as # if no locking needs to occur. yield else: if not lock.key == key: raise ValueError(_('Lock key must match target key: %(lock)s ' '!= %(target)s') % {'lock': lock.key, 'target': key}) if not lock.active: raise exception.ValidationError(_('Must be called within an ' 'active lock context.')) if not lock.expired: yield else: raise LockTimeout(target=key) class KeyValueStoreLock(object): """Basic KeyValueStoreLock context manager that hooks into the dogpile.cache backend mutex allowing for distributed locking on resources. This is only a write lock, and will not prevent reads from occurring. """ def __init__(self, mutex, key, locking_enabled=True): self.mutex = mutex self.key = key self.enabled = locking_enabled self.active = False self.acquire_time = 0 def acquire(self): if self.enabled: self.mutex.acquire() LOG.debug(_('KVS lock acquired for: %s'), self.key) self.active = True self.acquire_time = time.time() return self __enter__ = acquire @property def expired(self): if self.mutex.lock_timeout == 0: return False else: calculated = time.time() - self.acquire_time + LOCK_WINDOW return calculated > self.mutex.lock_timeout def release(self): if self.enabled: self.mutex.release() if not self.expired: LOG.debug(_('KVS lock released for: %s'), self.key) else: LOG.warning(_('KVS lock released (timeout reached) for: %s'), self.key) def __exit__(self, exc_type, exc_val, exc_tb): self.release() def get_key_value_store(name, kvs_region=None): """Instantiate a new :class:`.KeyValueStore` or return a previous instantiation that has the same name. """ global KEY_VALUE_STORE_REGISTRY _register_backends() key_value_store = KEY_VALUE_STORE_REGISTRY.get(name) if key_value_store is None: if kvs_region is None: kvs_region = region.make_region(name=name) key_value_store = KeyValueStore(kvs_region) KEY_VALUE_STORE_REGISTRY[name] = key_value_store return key_value_store keystone-2014.1/keystone/common/kvs/backends/0000775000175400017540000000000012323716511022307 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/kvs/backends/inmemdb.py0000664000175400017540000000360712323716267024312 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, 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. """ Keystone In-Memory Dogpile.cache backend implementation. """ import copy from dogpile.cache import api NO_VALUE = api.NO_VALUE class MemoryBackend(api.CacheBackend): """A backend that uses a plain dictionary. There is no size management, and values which are placed into the dictionary will remain until explicitly removed. Note that Dogpile's expiration of items is based on timestamps and does not remove them from the cache. E.g.:: from dogpile.cache import make_region region = make_region().configure( 'keystone.common.kvs.Memory' ) """ def __init__(self, arguments): self._db = {} def _isolate_value(self, value): if value is not NO_VALUE: return copy.deepcopy(value) return value def get(self, key): return self._isolate_value(self._db.get(key, NO_VALUE)) def get_multi(self, keys): return [self.get(key) for key in keys] def set(self, key, value): self._db[key] = self._isolate_value(value) def set_multi(self, mapping): for key, value in mapping.items(): self.set(key, value) def delete(self, key): self._db.pop(key, None) def delete_multi(self, keys): for key in keys: self.delete(key) keystone-2014.1/keystone/common/kvs/backends/memcached.py0000664000175400017540000001625512323716267024610 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, 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. """ Keystone Memcached dogpile.cache backend implementation. """ import random import time from dogpile.cache import api from dogpile.cache.backends import memcached from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) NO_VALUE = api.NO_VALUE VALID_DOGPILE_BACKENDS = dict(pylibmc=memcached.PylibmcBackend, bmemcached=memcached.BMemcachedBackend, memcached=memcached.MemcachedBackend) class MemcachedLock(object): """Simple distributed lock using memcached. This is an adaptation of the lock featured at http://amix.dk/blog/post/19386 """ def __init__(self, client_fn, key, lock_timeout, max_lock_attempts): self.client_fn = client_fn self.key = "_lock" + key self.lock_timeout = lock_timeout self.max_lock_attempts = max_lock_attempts def acquire(self, wait=True): client = self.client_fn() i = 0 while True: if client.add(self.key, 1, self.lock_timeout): return True elif not wait: return False else: sleep_time = (((i + 1) * random.random()) + 2 ** i) / 2.5 time.sleep(sleep_time) if i <= self.max_lock_attempts: i += 1 else: raise exception.UnexpectedError( _('Maximum lock attempts on %s occurred.') % self.key) def release(self): client = self.client_fn() client.delete(self.key) class MemcachedBackend(manager.Manager): """Pivot point to leverage the various dogpile.cache memcached backends. To specify a specific dogpile.cache memcached driver, pass the argument `memcached_driver` set to one of the provided memcached drivers (at this time `memcached`, `bmemcached`, `pylibmc` are valid). """ def __init__(self, arguments): self._key_mangler = None self.raw_no_expiry_keys = set(arguments.pop('no_expiry_keys', set())) self.no_expiry_hashed_keys = set() self.lock_timeout = arguments.pop('lock_timeout', None) self.max_lock_attempts = arguments.pop('max_lock_attempts', 15) # NOTE(morganfainberg): Remove distributed locking from the arguments # passed to the "real" backend if it exists. arguments.pop('distributed_lock', None) backend = arguments.pop('memcached_backend', None) if 'url' not in arguments: # FIXME(morganfainberg): Log deprecation warning for old-style # configuration once full dict_config style configuration for # KVS backends is supported. For now use the current memcache # section of the configuration. arguments['url'] = CONF.memcache.servers if backend is None: # NOTE(morganfainberg): Use the basic memcached backend if nothing # else is supplied. self.driver = VALID_DOGPILE_BACKENDS['memcached'](arguments) else: if backend not in VALID_DOGPILE_BACKENDS: raise ValueError( _('Backend `%(driver)s` is not a valid memcached ' 'backend. Valid drivers: %(driver_list)s') % {'driver': backend, 'driver_list': ','.join(VALID_DOGPILE_BACKENDS.keys())}) else: self.driver = VALID_DOGPILE_BACKENDS[backend](arguments) def _get_set_arguments_driver_attr(self, exclude_expiry=False): # NOTE(morganfainberg): Shallow copy the .set_arguments dict to # ensure no changes cause the values to change in the instance # variable. set_arguments = getattr(self.driver, 'set_arguments', {}).copy() if exclude_expiry: # NOTE(morganfainberg): Explicitly strip out the 'time' key/value # from the set_arguments in the case that this key isn't meant # to expire set_arguments.pop('time', None) return set_arguments def set(self, key, value): mapping = {key: value} self.set_multi(mapping) def set_multi(self, mapping): mapping_keys = set(mapping.keys()) no_expiry_keys = mapping_keys.intersection(self.no_expiry_hashed_keys) has_expiry_keys = mapping_keys.difference(self.no_expiry_hashed_keys) if no_expiry_keys: # NOTE(morganfainberg): For keys that have expiry excluded, # bypass the backend and directly call the client. Bypass directly # to the client is required as the 'set_arguments' are applied to # all ``set`` and ``set_multi`` calls by the driver, by calling # the client directly it is possible to exclude the ``time`` # argument to the memcached server. new_mapping = dict((k, mapping[k]) for k in no_expiry_keys) set_arguments = self._get_set_arguments_driver_attr( exclude_expiry=True) self.driver.client.set_multi(new_mapping, **set_arguments) if has_expiry_keys: new_mapping = dict((k, mapping[k]) for k in has_expiry_keys) self.driver.set_multi(new_mapping) @classmethod def from_config_dict(cls, config_dict, prefix): prefix_len = len(prefix) return cls( dict((key[prefix_len:], config_dict[key]) for key in config_dict if key.startswith(prefix))) @property def key_mangler(self): if self._key_mangler is None: self._key_mangler = self.driver.key_mangler return self._key_mangler @key_mangler.setter def key_mangler(self, key_mangler): if callable(key_mangler): self._key_mangler = key_mangler self._rehash_keys() elif key_mangler is None: # NOTE(morganfainberg): Set the hashed key map to the unhashed # list since we no longer have a key_mangler. self._key_mangler = None self.no_expiry_hashed_keys = self.raw_no_expiry_keys else: raise TypeError(_('`key_mangler` functions must be callable.')) def _rehash_keys(self): no_expire = set() for key in self.raw_no_expiry_keys: no_expire.add(self._key_mangler(key)) self.no_expiry_hashed_keys = no_expire def get_mutex(self, key): return MemcachedLock(lambda: self.driver.client, key, self.lock_timeout, self.max_lock_attempts) keystone-2014.1/keystone/common/kvs/backends/__init__.py0000664000175400017540000000000012323716267024416 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/kvs/__init__.py0000664000175400017540000000235412323716272022656 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, 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 dogpile.cache import region from keystone.common.kvs.core import * # flake8: noqa from keystone.common.kvs.legacy import Base, DictKvs, INMEMDB # flake8: noqa # NOTE(morganfainberg): Provided backends are registered here in the __init__ # for the kvs system. Any out-of-tree backends should be registered via the # ``backends`` option in the ``[kvs]`` section of the Keystone configuration # file. region.register_backend( 'openstack.kvs.Memory', 'keystone.common.kvs.backends.inmemdb', 'MemoryBackend') region.register_backend( 'openstack.kvs.Memcached', 'keystone.common.kvs.backends.memcached', 'MemcachedBackend') keystone-2014.1/keystone/common/kvs/legacy.py0000664000175400017540000000355712323716267022375 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone import exception from keystone.openstack.common import versionutils class DictKvs(dict): def get(self, key, default=None): try: if isinstance(self[key], dict): return self[key].copy() else: return self[key][:] except KeyError: if default is not None: return default raise exception.NotFound(target=key) def set(self, key, value): if isinstance(value, dict): self[key] = value.copy() else: self[key] = value[:] def delete(self, key): """Deletes an item, returning True on success, False otherwise.""" try: del self[key] except KeyError: raise exception.NotFound(target=key) INMEMDB = DictKvs() class Base(object): @versionutils.deprecated(versionutils.deprecated.ICEHOUSE, in_favor_of='keystone.common.kvs.KeyValueStore', remove_in=+1, what='keystone.common.kvs.Base') def __init__(self, db=None): if db is None: db = INMEMDB elif isinstance(db, DictKvs): db = db elif isinstance(db, dict): db = DictKvs(db) self.db = db keystone-2014.1/keystone/common/extension.py0000664000175400017540000000316412323716267022334 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. ADMIN_EXTENSIONS = {} PUBLIC_EXTENSIONS = {} def register_admin_extension(url_prefix, extension_data): """Register extension with collection of admin extensions. Extensions register the information here that will show up in the /extensions page as a way to indicate that the extension is active. url_prefix: unique key for the extension that will appear in the urls generated by the extension. extension_data is a dictionary. The expected fields are: 'name': short, human readable name of the extension 'namespace': xml namespace 'alias': identifier for the extension 'updated': date the extension was last updated 'description': text description of the extension 'links': hyperlinks to documents describing the extension """ ADMIN_EXTENSIONS[url_prefix] = extension_data def register_public_extension(url_prefix, extension_data): """Same as register_admin_extension but for public extensions.""" PUBLIC_EXTENSIONS[url_prefix] = extension_data keystone-2014.1/keystone/common/__init__.py0000664000175400017540000000000012323716267022041 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/cache/0000775000175400017540000000000012323716511020775 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/cache/core.py0000664000175400017540000001663212323716267022317 0ustar jenkinsjenkins00000000000000# Copyright 2013 Metacloud # # 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. """Keystone Caching Layer Implementation.""" import dogpile.cache from dogpile.cache import proxy from dogpile.cache import util from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) make_region = dogpile.cache.make_region dogpile.cache.register_backend( 'keystone.common.cache.noop', 'keystone.common.cache.backends.noop', 'NoopCacheBackend') dogpile.cache.register_backend( 'keystone.cache.mongo', 'keystone.common.cache.backends.mongo', 'MongoCacheBackend') class DebugProxy(proxy.ProxyBackend): """Extra Logging ProxyBackend.""" # NOTE(morganfainberg): Pass all key/values through repr to ensure we have # a clean description of the information. Without use of repr, it might # be possible to run into encode/decode error(s). For logging/debugging # purposes encode/decode is irrelevant and we should be looking at the # data exactly as it stands. def get(self, key): value = self.proxied.get(key) LOG.debug(_('CACHE_GET: Key: "%(key)r" Value: "%(value)r"'), {'key': key, 'value': value}) return value def get_multi(self, keys): values = self.proxied.get_multi(keys) LOG.debug(_('CACHE_GET_MULTI: "%(keys)r" Values: "%(values)r"'), {'keys': keys, 'values': values}) return values def set(self, key, value): LOG.debug(_('CACHE_SET: Key: "%(key)r" Value: "%(value)r"'), {'key': key, 'value': value}) return self.proxied.set(key, value) def set_multi(self, keys): LOG.debug(_('CACHE_SET_MULTI: "%r"'), keys) self.proxied.set_multi(keys) def delete(self, key): self.proxied.delete(key) LOG.debug(_('CACHE_DELETE: "%r"'), key) def delete_multi(self, keys): LOG.debug(_('CACHE_DELETE_MULTI: "%r"'), keys) self.proxied.delete_multi(keys) def build_cache_config(): """Build the cache region dictionary configuration. :param conf: configuration object for keystone :returns: dict """ prefix = CONF.cache.config_prefix conf_dict = {} conf_dict['%s.backend' % prefix] = CONF.cache.backend conf_dict['%s.expiration_time' % prefix] = CONF.cache.expiration_time for argument in CONF.cache.backend_argument: try: (argname, argvalue) = argument.split(':', 1) except ValueError: msg = _('Unable to build cache config-key. Expected format ' '":". Skipping unknown format: %s') LOG.error(msg, argument) continue arg_key = '.'.join([prefix, 'arguments', argname]) conf_dict[arg_key] = argvalue LOG.debug(_('Keystone Cache Config: %s'), conf_dict) return conf_dict def configure_cache_region(region): """Configure a cache region. :param region: optional CacheRegion object, if not provided a new region will be instantiated :raises: exception.ValidationError :returns: dogpile.cache.CacheRegion """ if not isinstance(region, dogpile.cache.CacheRegion): raise exception.ValidationError( _('region not type dogpile.cache.CacheRegion')) if 'backend' not in region.__dict__: # NOTE(morganfainberg): this is how you tell if a region is configured. # There is a request logged with dogpile.cache upstream to make this # easier / less ugly. config_dict = build_cache_config() region.configure_from_config(config_dict, '%s.' % CONF.cache.config_prefix) if CONF.cache.debug_cache_backend: region.wrap(DebugProxy) # NOTE(morganfainberg): if the backend requests the use of a # key_mangler, we should respect that key_mangler function. If a # key_mangler is not defined by the backend, use the sha1_mangle_key # mangler provided by dogpile.cache. This ensures we always use a fixed # size cache-key. This is toggle-able for debug purposes; if disabled # this could cause issues with certain backends (such as memcached) and # its limited key-size. if region.key_mangler is None: if CONF.cache.use_key_mangler: region.key_mangler = util.sha1_mangle_key for class_path in CONF.cache.proxies: # NOTE(morganfainberg): if we have any proxy wrappers, we should # ensure they are added to the cache region's backend. Since # configure_from_config doesn't handle the wrap argument, we need # to manually add the Proxies. For information on how the # ProxyBackends work, see the dogpile.cache documents on # "changing-backend-behavior" cls = importutils.import_class(class_path) LOG.debug(_("Adding cache-proxy '%s' to backend."), class_path) region.wrap(cls) return region def should_cache_fn(section): """Build a function that returns a config section's caching status. For any given driver in keystone that has caching capabilities, a boolean config option for that driver's section (e.g. ``token``) should exist and default to ``True``. This function will use that value to tell the caching decorator if caching for that driver is enabled. To properly use this with the decorator, pass this function the configuration section and assign the result to a variable. Pass the new variable to the caching decorator as the named argument ``should_cache_fn``. e.g.:: from keystone.common import cache SHOULD_CACHE = cache.should_cache_fn('token') @cache.on_arguments(should_cache_fn=SHOULD_CACHE) def function(arg1, arg2): ... :param section: name of the configuration section to examine :type section: string :returns: function reference """ def should_cache(value): if not CONF.cache.enabled: return False conf_group = getattr(CONF, section) return getattr(conf_group, 'caching', True) return should_cache def key_generate_to_str(s): # NOTE(morganfainberg): Since we need to stringify all arguments, attempt # to stringify and handle the Unicode error explicitly as needed. try: return str(s) except UnicodeEncodeError: return s.encode('utf-8') def function_key_generator(namespace, fn, to_str=key_generate_to_str): # NOTE(morganfainberg): This wraps dogpile.cache's default # function_key_generator to change the default to_str mechanism. return util.function_key_generator(namespace, fn, to_str=to_str) REGION = dogpile.cache.make_region( function_key_generator=function_key_generator) on_arguments = REGION.cache_on_arguments keystone-2014.1/keystone/common/cache/backends/0000775000175400017540000000000012323716511022547 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/cache/backends/mongo.py0000664000175400017540000005576512323716267024272 0ustar jenkinsjenkins00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import abc import datetime from dogpile.cache import api from dogpile.cache import util as dp_util import six from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone.openstack.common import log from keystone.openstack.common import timeutils NO_VALUE = api.NO_VALUE LOG = log.getLogger(__name__) class MongoCacheBackend(api.CacheBackend): """A MongoDB based caching backend implementing dogpile backend APIs. Arguments accepted in the arguments dictionary: :param db_hosts: string (required), hostname or IP address of the MongoDB server instance. This can be a single MongoDB connection URI, or a list of MongoDB connection URIs. :param db_name: string (required), the name of the database to be used. :param cache_collection: string (required), the name of collection to store cached data. *Note:* Different collection name can be provided if there is need to create separate container (i.e. collection) for cache data. So region configuration is done per collection. Following are optional parameters for MongoDB backend configuration, :param username: string, the name of the user to authenticate. :param password: string, the password of the user to authenticate. :param max_pool_size: integer, the maximum number of connections that the pool will open simultaneously. By default the pool size is 10. :param w: integer, write acknowledgement for MongoDB client If not provided, then no default is set on MongoDB and then write acknowledgement behavior occurs as per MongoDB default. This parameter name is same as what is used in MongoDB docs. This value is specified at collection level so its applicable to `cache_collection` db write operations. If this is a replica set, write operations will block until they have been replicated to the specified number or tagged set of servers. Setting w=0 disables write acknowledgement and all other write concern options. :param read_preference: string, the read preference mode for MongoDB client Expected value is ``primary``, ``primaryPreferred``, ``secondary``, ``secondaryPreferred``, or ``nearest``. This read_preference is specified at collection level so its applicable to `cache_collection` db read operations. :param use_replica: boolean, flag to indicate if replica client to be used. Default is `False`. `replicaset_name` value is required if `True`. :param replicaset_name: string, name of replica set. Becomes required if `use_replica` is `True` :param son_manipulator: string, name of class with module name which implements MongoDB SONManipulator. Default manipulator used is :class:`.BaseTransform`. This manipulator is added per database. In multiple cache configurations, the manipulator name should be same if same database name ``db_name`` is used in those configurations. SONManipulator is used to manipulate custom data types as they are saved or retrieved from MongoDB. Custom impl is only needed if cached data is custom class and needs transformations when saving or reading from db. If dogpile cached value contains built-in data types, then BaseTransform class is sufficient as it already handles dogpile CachedValue class transformation. :param mongo_ttl_seconds: integer, interval in seconds to indicate maximum time-to-live value. If value is greater than 0, then its assumed that cache_collection needs to be TTL type (has index at 'doc_date' field). By default, the value is -1 and its disabled. Reference: .. NOTE:: This parameter is different from Dogpile own expiration_time, which is the number of seconds after which Dogpile will consider the value to be expired. When Dogpile considers a value to be expired, it continues to use the value until generation of a new value is complete, when using CacheRegion.get_or_create(). Therefore, if you are setting `mongo_ttl_seconds`, you will want to make sure it is greater than expiration_time by at least enough seconds for new values to be generated, else the value would not be available during a regeneration, forcing all threads to wait for a regeneration each time a value expires. :param ssl: boolean, If True, create the connection to the server using SSL. Default is `False`. Client SSL connection parameters depends on server side SSL setup. For further reference on SSL configuration: :param ssl_keyfile: string, the private keyfile used to identify the local connection against mongod. If included with the certfile then only the `ssl_certfile` is needed. Used only when `ssl` is `True`. :param ssl_certfile: string, the certificate file used to identify the local connection against mongod. Used only when `ssl` is `True`. :param ssl_ca_certs: string, the ca_certs file contains a set of concatenated 'certification authority' certificates, which are used to validate certificates passed from the other end of the connection. Used only when `ssl` is `True`. :param ssl_cert_reqs: string, the parameter cert_reqs specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided. It must be one of the three values ``ssl.CERT_NONE`` (certificates ignored), ``ssl.CERT_OPTIONAL`` (not required, but validated if provided), or ``ssl.CERT_REQUIRED`` (required and validated). If the value of this parameter is not ``ssl.CERT_NONE``, then the ssl_ca_certs parameter must point to a file of CA certificates. Used only when `ssl` is `True`. Rest of arguments are passed to mongo calls for read, write and remove. So related options can be specified to pass to these operations. Further details of various supported arguments can be referred from """ def __init__(self, arguments): self.api = MongoApi(arguments) @dp_util.memoized_property def client(self): """Initializes MongoDB connection and collection defaults. This initialization is done only once and performed as part of lazy inclusion of MongoDB dependency i.e. add imports only if related backend is used. :return: :class:`.MongoApi` instance """ self.api.get_cache_collection() return self.api def get(self, key): value = self.client.get(key) if value is None: return NO_VALUE else: return value def get_multi(self, keys): values = self.client.get_multi(keys) return [ NO_VALUE if key not in values else values[key] for key in keys ] def set(self, key, value): self.client.set(key, value) def set_multi(self, mapping): self.client.set_multi(mapping) def delete(self, key): self.client.delete(key) def delete_multi(self, keys): self.client.delete_multi(keys) class MongoApi(object): """Class handling MongoDB specific functionality. This class uses PyMongo APIs internally to create database connection with configured pool size, ensures unique index on key, does database authentication and ensure TTL collection index if configured so. This class also serves as handle to cache collection for dogpile cache APIs. In a single deployment, multiple cache configuration can be defined. In that case of multiple cache collections usage, db client connection pool is shared when cache collections are within same database. """ # class level attributes for re-use of db client connection and collection _DB = {} # dict of db_name: db connection reference _MONGO_COLLS = {} # dict of cache_collection : db collection reference def __init__(self, arguments): self._init_args(arguments) self._data_manipulator = None def _init_args(self, arguments): """Helper logic for collecting and parsing MongoDB specific arguments. The arguments passed in are separated out in connection specific setting and rest of arguments are passed to create/update/delete db operations. """ self.conn_kwargs = {} # connection specific arguments self.hosts = arguments.pop('db_hosts', None) if self.hosts is None: msg = _('db_hosts value is required') raise exception.ValidationError(message=msg) self.db_name = arguments.pop('db_name', None) if self.db_name is None: msg = _('database db_name is required') raise exception.ValidationError(message=msg) self.cache_collection = arguments.pop('cache_collection', None) if self.cache_collection is None: msg = _('cache_collection name is required') raise exception.ValidationError(message=msg) self.username = arguments.pop('username', None) self.password = arguments.pop('password', None) self.max_pool_size = arguments.pop('max_pool_size', 10) self.w = arguments.pop('w', -1) try: self.w = int(self.w) except ValueError: msg = _('integer value expected for w (write concern attribute)') raise exception.ValidationError(message=msg) self.read_preference = arguments.pop('read_preference', None) self.use_replica = arguments.pop('use_replica', False) if self.use_replica: if arguments.get('replicaset_name') is None: msg = _('replicaset_name required when use_replica is True') raise exception.ValidationError(message=msg) self.replicaset_name = arguments.get('replicaset_name') self.son_manipulator = arguments.pop('son_manipulator', None) # set if mongo collection needs to be TTL type. # This needs to be max ttl for any cache entry. # By default, -1 means don't use TTL collection. # With ttl set, it creates related index and have doc_date field with # needed expiration interval self.ttl_seconds = arguments.pop('mongo_ttl_seconds', -1) try: self.ttl_seconds = int(self.ttl_seconds) except ValueError: msg = _('integer value expected for mongo_ttl_seconds') raise exception.ValidationError(message=msg) self.conn_kwargs['ssl'] = arguments.pop('ssl', False) if self.conn_kwargs['ssl']: ssl_keyfile = arguments.pop('ssl_keyfile', None) ssl_certfile = arguments.pop('ssl_certfile', None) ssl_ca_certs = arguments.pop('ssl_ca_certs', None) ssl_cert_reqs = arguments.pop('ssl_cert_reqs', None) if ssl_keyfile: self.conn_kwargs['ssl_keyfile'] = ssl_keyfile if ssl_certfile: self.conn_kwargs['ssl_certfile'] = ssl_certfile if ssl_ca_certs: self.conn_kwargs['ssl_ca_certs'] = ssl_ca_certs if ssl_cert_reqs: self.conn_kwargs['ssl_cert_reqs'] = \ self._ssl_cert_req_type(ssl_cert_reqs) # rest of arguments are passed to mongo crud calls self.meth_kwargs = arguments def _ssl_cert_req_type(self, req_type): try: import ssl except ImportError: raise exception.ValidationError(_('no ssl support available')) req_type = req_type.upper() try: return { 'NONE': ssl.CERT_NONE, 'OPTIONAL': ssl.CERT_OPTIONAL, 'REQUIRED': ssl.CERT_REQUIRED }[req_type] except KeyError: msg = _('Invalid ssl_cert_reqs value of %s, must be one of ' '"NONE", "OPTIONAL", "REQUIRED"') % (req_type) raise exception.ValidationError(message=msg) def _get_db(self): # defer imports until backend is used global pymongo import pymongo if self.use_replica: connection = pymongo.MongoReplicaSetClient( host=self.hosts, replicaSet=self.replicaset_name, max_pool_size=self.max_pool_size, **self.conn_kwargs) else: # used for standalone node or mongos in sharded setup connection = pymongo.MongoClient( host=self.hosts, max_pool_size=self.max_pool_size, **self.conn_kwargs) database = getattr(connection, self.db_name) self._assign_data_mainpulator() database.add_son_manipulator(self._data_manipulator) if self.username and self.password: database.authenticate(self.username, self.password) return database def _assign_data_mainpulator(self): if self._data_manipulator is None: if self.son_manipulator: self._data_manipulator = importutils.import_object( self.son_manipulator) else: self._data_manipulator = BaseTransform() def _get_doc_date(self): if self.ttl_seconds > 0: expire_delta = datetime.timedelta(seconds=self.ttl_seconds) doc_date = timeutils.utcnow() + expire_delta else: doc_date = timeutils.utcnow() return doc_date def get_cache_collection(self): if self.cache_collection not in self._MONGO_COLLS: global pymongo import pymongo # re-use db client connection if already defined as part of # earlier dogpile cache configuration if self.db_name not in self._DB: self._DB[self.db_name] = self._get_db() coll = getattr(self._DB[self.db_name], self.cache_collection) self._assign_data_mainpulator() if self.read_preference: self.read_preference = pymongo.read_preferences.\ mongos_enum(self.read_preference) coll.read_preference = self.read_preference if self.w > -1: coll.write_concern['w'] = self.w if self.ttl_seconds > 0: kwargs = {'expireAfterSeconds': self.ttl_seconds} coll.ensure_index('doc_date', cache_for=5, **kwargs) else: self._validate_ttl_index(coll, self.cache_collection, self.ttl_seconds) self._MONGO_COLLS[self.cache_collection] = coll return self._MONGO_COLLS[self.cache_collection] def _get_cache_entry(self, key, value, meta, doc_date): """MongoDB cache data representation. Storing cache key as ``_id`` field as MongoDB by default creates unique index on this field. So no need to create separate field and index for storing cache key. Cache data has additional ``doc_date`` field for MongoDB TTL collection support. """ return dict(_id=key, value=value, meta=meta, doc_date=doc_date) def _validate_ttl_index(self, collection, coll_name, ttl_seconds): """Checks if existing TTL index is removed on a collection. This logs warning when existing collection has TTL index defined and new cache configuration tries to disable index with ``mongo_ttl_seconds < 0``. In that case, existing index needs to be addressed first to make new configuration effective. Refer to MongoDB documentation around TTL index for further details. """ indexes = collection.index_information() for indx_name, index_data in six.iteritems(indexes): if all(k in index_data for k in ('key', 'expireAfterSeconds')): existing_value = index_data['expireAfterSeconds'] fld_present = 'doc_date' in index_data['key'][0] if fld_present and existing_value > -1 and ttl_seconds < 1: msg = _('TTL index already exists on db collection ' '<%(c_name)s>, remove index <%(indx_name)s> first' ' to make updated mongo_ttl_seconds value to be ' ' effective') LOG.warn(msg, {'c_name': coll_name, 'indx_name': indx_name}) def get(self, key): critieria = {'_id': key} result = self.get_cache_collection().find_one(spec_or_id=critieria, **self.meth_kwargs) if result: return result['value'] else: return None def get_multi(self, keys): db_results = self._get_results_as_dict(keys) return dict((doc['_id'], doc['value']) for doc in six.itervalues(db_results)) def _get_results_as_dict(self, keys): critieria = {'_id': {'$in': keys}} db_results = self.get_cache_collection().find(spec=critieria, **self.meth_kwargs) return dict((doc['_id'], doc) for doc in db_results) def set(self, key, value): doc_date = self._get_doc_date() ref = self._get_cache_entry(key, value.payload, value.metadata, doc_date) spec = {'_id': key} # find and modify does not have manipulator support # so need to do conversion as part of input document ref = self._data_manipulator.transform_incoming(ref, self) self.get_cache_collection().find_and_modify(spec, ref, upsert=True, **self.meth_kwargs) def set_multi(self, mapping): """Insert multiple documents specified as key, value pairs. In this case, multiple documents can be added via insert provided they do not exist. Update of multiple existing documents is done one by one """ doc_date = self._get_doc_date() insert_refs = [] update_refs = [] existing_docs = self._get_results_as_dict(mapping.keys()) for key, value in mapping.items(): ref = self._get_cache_entry(key, value.payload, value.metadata, doc_date) if key in existing_docs: ref['_id'] = existing_docs[key]['_id'] update_refs.append(ref) else: insert_refs.append(ref) if insert_refs: self.get_cache_collection().insert(insert_refs, manipulate=True, **self.meth_kwargs) for upd_doc in update_refs: self.get_cache_collection().save(upd_doc, manipulate=True, **self.meth_kwargs) def delete(self, key): critieria = {'_id': key} self.get_cache_collection().remove(spec_or_id=critieria, **self.meth_kwargs) def delete_multi(self, keys): critieria = {'_id': {'$in': keys}} self.get_cache_collection().remove(spec_or_id=critieria, **self.meth_kwargs) @six.add_metaclass(abc.ABCMeta) class AbstractManipulator(object): """Abstract class with methods which need to be implemented for custom manipulation. Adding this as a base class for :class:`.BaseTransform` instead of adding import dependency of pymongo specific class i.e. `pymongo.son_manipulator.SONManipulator` and using that as base class. This is done to avoid pymongo dependency if MongoDB backend is not used. """ @abc.abstractmethod def transform_incoming(self, son, collection): """Used while saving data to MongoDB. :param son: the SON object to be inserted into the database :param collection: the collection the object is being inserted into :returns: transformed SON object """ raise exception.NotImplemented() @abc.abstractmethod def transform_outgoing(self, son, collection): """Used while reading data from MongoDB. :param son: the SON object being retrieved from the database :param collection: the collection this object was stored in :returns: transformed SON object """ raise exception.NotImplemented() def will_copy(self): """Will this SON manipulator make a copy of the incoming document? Derived classes that do need to make a copy should override this method, returning `True` instead of `False`. :returns: boolean """ return False class BaseTransform(AbstractManipulator): """Base transformation class to store and read dogpile cached data from MongoDB. This is needed as dogpile internally stores data as a custom class i.e. dogpile.cache.api.CachedValue Note: Custom manipulator needs to always override ``transform_incoming`` and ``transform_outgoing`` methods. MongoDB manipulator logic specifically checks that overriden method in instance and its super are different. """ def transform_incoming(self, son, collection): """Used while saving data to MongoDB.""" for (key, value) in son.items(): if isinstance(value, api.CachedValue): son[key] = value.payload # key is 'value' field here son['meta'] = value.metadata elif isinstance(value, dict): # Make sure we recurse into sub-docs son[key] = self.transform_incoming(value, collection) return son def transform_outgoing(self, son, collection): """Used while reading data from MongoDB.""" metadata = None # make sure its top level dictionary with all expected fields names # present if isinstance(son, dict) and all(k in son for k in ('_id', 'value', 'meta', 'doc_date')): payload = son.pop('value', None) metadata = son.pop('meta', None) for (key, value) in son.items(): if isinstance(value, dict): son[key] = self.transform_outgoing(value, collection) if metadata is not None: son['value'] = api.CachedValue(payload, metadata) return son keystone-2014.1/keystone/common/cache/backends/noop.py0000664000175400017540000000262212323716267024106 0ustar jenkinsjenkins00000000000000# Copyright 2013 Metacloud # # 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 dogpile.cache import api NO_VALUE = api.NO_VALUE class NoopCacheBackend(api.CacheBackend): """A no op backend as a default caching backend. The no op backend is provided as the default caching backend for keystone to ensure that ``dogpile.cache.memory`` is not used in any real-world circumstances unintentionally. ``dogpile.cache.memory`` does not have a mechanism to cleanup it's internal dict and therefore could cause run-away memory utilization. """ def __init__(self, *args): return def get(self, key): return NO_VALUE def get_multi(self, keys): return [NO_VALUE for x in keys] def set(self, key, value): return def set_multi(self, mapping): return def delete(self, key): return def delete_multi(self, keys): return keystone-2014.1/keystone/common/cache/backends/__init__.py0000664000175400017540000000000012323716267024656 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/cache/__init__.py0000664000175400017540000000117012323716272023111 0ustar jenkinsjenkins00000000000000# Copyright 2013 Metacloud # # 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 keystone.common.cache.core import * # flake8: noqa keystone-2014.1/keystone/common/ldap/0000775000175400017540000000000012323716511020652 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/common/ldap/core.py0000664000175400017540000007331012323716272022164 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import os.path import ldap import ldap.filter import six from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log LOG = log.getLogger(__name__) LDAP_VALUES = {'TRUE': True, 'FALSE': False} CONTROL_TREEDELETE = '1.2.840.113556.1.4.805' LDAP_SCOPES = {'one': ldap.SCOPE_ONELEVEL, 'sub': ldap.SCOPE_SUBTREE} LDAP_DEREF = {'always': ldap.DEREF_ALWAYS, 'default': None, 'finding': ldap.DEREF_FINDING, 'never': ldap.DEREF_NEVER, 'searching': ldap.DEREF_SEARCHING} LDAP_TLS_CERTS = {'never': ldap.OPT_X_TLS_NEVER, 'demand': ldap.OPT_X_TLS_DEMAND, 'allow': ldap.OPT_X_TLS_ALLOW} def py2ldap(val): if isinstance(val, str): return val elif isinstance(val, bool): return 'TRUE' if val else 'FALSE' else: return str(val) def ldap2py(val): try: return LDAP_VALUES[val] except KeyError: pass try: return int(val) except ValueError: pass return val def safe_iter(attrs): if attrs is None: return elif isinstance(attrs, list): for e in attrs: yield e else: yield attrs def parse_deref(opt): try: return LDAP_DEREF[opt] except KeyError: raise ValueError(_('Invalid LDAP deref option: %(option)s. ' 'Choose one of: %(options)s') % {'option': opt, 'options': ', '.join(LDAP_DEREF.keys()), }) def parse_tls_cert(opt): try: return LDAP_TLS_CERTS[opt] except KeyError: raise ValueError(_( 'Invalid LDAP TLS certs option: %(option)s. ' 'Choose one of: %(options)s') % { 'option': opt, 'options': ', '.join(LDAP_TLS_CERTS.keys())}) def ldap_scope(scope): try: return LDAP_SCOPES[scope] except KeyError: raise ValueError( _('Invalid LDAP scope: %(scope)s. Choose one of: %(options)s') % { 'scope': scope, 'options': ', '.join(LDAP_SCOPES.keys())}) _HANDLERS = {} def register_handler(prefix, handler): _HANDLERS[prefix] = handler def get_handler(conn_url): for prefix, handler in six.iteritems(_HANDLERS): if conn_url.startswith(prefix): return handler return LdapWrapper class BaseLdap(object): DEFAULT_SUFFIX = "dc=example,dc=com" DEFAULT_OU = None DEFAULT_STRUCTURAL_CLASSES = None DEFAULT_ID_ATTR = 'cn' DEFAULT_OBJECTCLASS = None DEFAULT_FILTER = None DEFAULT_EXTRA_ATTR_MAPPING = [] DUMB_MEMBER_DN = 'cn=dumb,dc=nonexistent' NotFound = None notfound_arg = None options_name = None model = None attribute_options_names = {} immutable_attrs = [] attribute_ignore = [] tree_dn = None def __init__(self, conf): self.LDAP_URL = conf.ldap.url self.LDAP_USER = conf.ldap.user self.LDAP_PASSWORD = conf.ldap.password self.LDAP_SCOPE = ldap_scope(conf.ldap.query_scope) self.alias_dereferencing = parse_deref(conf.ldap.alias_dereferencing) self.page_size = conf.ldap.page_size self.use_tls = conf.ldap.use_tls self.tls_cacertfile = conf.ldap.tls_cacertfile self.tls_cacertdir = conf.ldap.tls_cacertdir self.tls_req_cert = parse_tls_cert(conf.ldap.tls_req_cert) self.attribute_mapping = {} self.chase_referrals = conf.ldap.chase_referrals if self.options_name is not None: self.suffix = conf.ldap.suffix if self.suffix is None: self.suffix = self.DEFAULT_SUFFIX dn = '%s_tree_dn' % self.options_name self.tree_dn = (getattr(conf.ldap, dn) or '%s,%s' % (self.DEFAULT_OU, self.suffix)) idatt = '%s_id_attribute' % self.options_name self.id_attr = getattr(conf.ldap, idatt) or self.DEFAULT_ID_ATTR objclass = '%s_objectclass' % self.options_name self.object_class = (getattr(conf.ldap, objclass) or self.DEFAULT_OBJECTCLASS) for k, v in six.iteritems(self.attribute_options_names): v = '%s_%s_attribute' % (self.options_name, v) self.attribute_mapping[k] = getattr(conf.ldap, v) attr_mapping_opt = ('%s_additional_attribute_mapping' % self.options_name) attr_mapping = (getattr(conf.ldap, attr_mapping_opt) or self.DEFAULT_EXTRA_ATTR_MAPPING) self.extra_attr_mapping = self._parse_extra_attrs(attr_mapping) ldap_filter = '%s_filter' % self.options_name self.ldap_filter = getattr(conf.ldap, ldap_filter) or self.DEFAULT_FILTER allow_create = '%s_allow_create' % self.options_name self.allow_create = getattr(conf.ldap, allow_create) allow_update = '%s_allow_update' % self.options_name self.allow_update = getattr(conf.ldap, allow_update) allow_delete = '%s_allow_delete' % self.options_name self.allow_delete = getattr(conf.ldap, allow_delete) self.structural_classes = self.DEFAULT_STRUCTURAL_CLASSES if self.notfound_arg is None: self.notfound_arg = self.options_name + '_id' attribute_ignore = '%s_attribute_ignore' % self.options_name self.attribute_ignore = getattr(conf.ldap, attribute_ignore) self.use_dumb_member = getattr(conf.ldap, 'use_dumb_member') self.dumb_member = (getattr(conf.ldap, 'dumb_member') or self.DUMB_MEMBER_DN) self.subtree_delete_enabled = getattr(conf.ldap, 'allow_subtree_delete') def _not_found(self, object_id): if self.NotFound is None: return exception.NotFound(target=object_id) else: return self.NotFound(**{self.notfound_arg: object_id}) def _parse_extra_attrs(self, option_list): mapping = {} for item in option_list: try: ldap_attr, attr_map = item.split(':') except Exception: LOG.warn(_( 'Invalid additional attribute mapping: "%s". ' 'Format must be :'), item) continue if attr_map not in self.attribute_mapping: LOG.warn(_('Invalid additional attribute mapping: "%(item)s". ' 'Value "%(attr_map)s" must use one of %(keys)s.'), {'item': item, 'attr_map': attr_map, 'keys': ', '.join(self.attribute_mapping.keys())}) continue mapping[ldap_attr] = attr_map return mapping def get_connection(self, user=None, password=None): handler = get_handler(self.LDAP_URL) conn = handler(self.LDAP_URL, self.page_size, alias_dereferencing=self.alias_dereferencing, use_tls=self.use_tls, tls_cacertfile=self.tls_cacertfile, tls_cacertdir=self.tls_cacertdir, tls_req_cert=self.tls_req_cert, chase_referrals=self.chase_referrals) if user is None: user = self.LDAP_USER if password is None: password = self.LDAP_PASSWORD # not all LDAP servers require authentication, so we don't bind # if we don't have any user/pass if user and password: conn.simple_bind_s(user, password) return conn def _id_to_dn_string(self, object_id): return '%s=%s,%s' % (self.id_attr, ldap.dn.escape_dn_chars(str(object_id)), self.tree_dn) def _id_to_dn(self, object_id): if self.LDAP_SCOPE == ldap.SCOPE_ONELEVEL: return self._id_to_dn_string(object_id) conn = self.get_connection() try: search_result = conn.search_s( self.tree_dn, self.LDAP_SCOPE, '(&(%(id_attr)s=%(id)s)(objectclass=%(objclass)s))' % {'id_attr': self.id_attr, 'id': ldap.filter.escape_filter_chars(str(object_id)), 'objclass': self.object_class}) finally: conn.unbind_s() if search_result: dn, attrs = search_result[0] return dn else: return self._id_to_dn_string(object_id) @staticmethod def _dn_to_id(dn): return ldap.dn.str2dn(dn)[0][0][1] def _ldap_res_to_model(self, res): obj = self.model(id=self._dn_to_id(res[0])) for k in obj.known_keys: if k in self.attribute_ignore: continue try: v = res[1][self.attribute_mapping.get(k, k)] except KeyError: pass else: try: obj[k] = v[0] except IndexError: obj[k] = None return obj def check_allow_create(self): if not self.allow_create: action = _('LDAP %s create') % self.options_name raise exception.ForbiddenAction(action=action) def check_allow_update(self): if not self.allow_update: action = _('LDAP %s update') % self.options_name raise exception.ForbiddenAction(action=action) def check_allow_delete(self): if not self.allow_delete: action = _('LDAP %s delete') % self.options_name raise exception.ForbiddenAction(action=action) def affirm_unique(self, values): if values.get('name') is not None: try: self.get_by_name(values['name']) except exception.NotFound: pass else: raise exception.Conflict(type=self.options_name, details=_('Duplicate name, %s.') % values['name']) if values.get('id') is not None: try: self.get(values['id']) except exception.NotFound: pass else: raise exception.Conflict(type=self.options_name, details=_('Duplicate ID, %s.') % values['id']) def create(self, values): self.affirm_unique(values) conn = self.get_connection() object_classes = self.structural_classes + [self.object_class] attrs = [('objectClass', object_classes)] for k, v in six.iteritems(values): if k == 'id' or k in self.attribute_ignore: continue if v is not None: attr_type = self.attribute_mapping.get(k, k) if attr_type is not None: attrs.append((attr_type, [v])) extra_attrs = [attr for attr, name in six.iteritems(self.extra_attr_mapping) if name == k] for attr in extra_attrs: attrs.append((attr, [v])) if 'groupOfNames' in object_classes and self.use_dumb_member: attrs.append(('member', [self.dumb_member])) try: conn.add_s(self._id_to_dn(values['id']), attrs) finally: conn.unbind_s() return values def _ldap_get(self, object_id, ldap_filter=None): conn = self.get_connection() query = ('(&(%(id_attr)s=%(id)s)' '%(filter)s' '(objectClass=%(object_class)s))' % {'id_attr': self.id_attr, 'id': ldap.filter.escape_filter_chars(str(object_id)), 'filter': (ldap_filter or self.ldap_filter or ''), 'object_class': self.object_class}) try: attrs = list(set((self.attribute_mapping.values() + self.extra_attr_mapping.keys()))) res = conn.search_s(self.tree_dn, self.LDAP_SCOPE, query, attrs) except ldap.NO_SUCH_OBJECT: return None finally: conn.unbind_s() try: return res[0] except IndexError: return None def _ldap_get_all(self, ldap_filter=None): conn = self.get_connection() query = '(&%s(objectClass=%s))' % (ldap_filter or self.ldap_filter or '', self.object_class) try: return conn.search_s(self.tree_dn, self.LDAP_SCOPE, query, self.attribute_mapping.values()) except ldap.NO_SUCH_OBJECT: return [] finally: conn.unbind_s() def get(self, object_id, ldap_filter=None): res = self._ldap_get(object_id, ldap_filter) if res is None: raise self._not_found(object_id) else: return self._ldap_res_to_model(res) def get_by_name(self, name, ldap_filter=None): query = ('(%s=%s)' % (self.attribute_mapping['name'], ldap.filter.escape_filter_chars(name))) res = self.get_all(query) try: return res[0] except IndexError: raise self._not_found(name) def get_all(self, ldap_filter=None): return [self._ldap_res_to_model(x) for x in self._ldap_get_all(ldap_filter)] def update(self, object_id, values, old_obj=None): if old_obj is None: old_obj = self.get(object_id) modlist = [] for k, v in six.iteritems(values): if k == 'id' or k in self.attribute_ignore: continue # attribute value has not changed if k in old_obj and old_obj[k] == v: continue if k in self.immutable_attrs: msg = (_("Cannot change %(option_name)s %(attr)s") % {'option_name': self.options_name, 'attr': k}) raise exception.ValidationError(msg) if v is None: if old_obj.get(k) is not None: modlist.append((ldap.MOD_DELETE, self.attribute_mapping.get(k, k), None)) continue current_value = old_obj.get(k) if current_value is None: op = ldap.MOD_ADD modlist.append((op, self.attribute_mapping.get(k, k), [v])) elif current_value != v: op = ldap.MOD_REPLACE modlist.append((op, self.attribute_mapping.get(k, k), [v])) if modlist: conn = self.get_connection() try: conn.modify_s(self._id_to_dn(object_id), modlist) except ldap.NO_SUCH_OBJECT: raise self._not_found(object_id) finally: conn.unbind_s() return self.get(object_id) def delete(self, object_id): conn = self.get_connection() try: conn.delete_s(self._id_to_dn(object_id)) except ldap.NO_SUCH_OBJECT: raise self._not_found(object_id) finally: conn.unbind_s() def deleteTree(self, object_id): conn = self.get_connection() tree_delete_control = ldap.controls.LDAPControl(CONTROL_TREEDELETE, 0, None) try: conn.delete_ext_s(self._id_to_dn(object_id), serverctrls=[tree_delete_control]) except ldap.NO_SUCH_OBJECT: raise self._not_found(object_id) finally: conn.unbind_s() class LdapWrapper(object): def __init__(self, url, page_size, alias_dereferencing=None, use_tls=False, tls_cacertfile=None, tls_cacertdir=None, tls_req_cert='demand', chase_referrals=None): LOG.debug(_("LDAP init: url=%s"), url) LOG.debug(_('LDAP init: use_tls=%(use_tls)s\n' 'tls_cacertfile=%(tls_cacertfile)s\n' 'tls_cacertdir=%(tls_cacertdir)s\n' 'tls_req_cert=%(tls_req_cert)s\n' 'tls_avail=%(tls_avail)s\n'), {'use_tls': use_tls, 'tls_cacertfile': tls_cacertfile, 'tls_cacertdir': tls_cacertdir, 'tls_req_cert': tls_req_cert, 'tls_avail': ldap.TLS_AVAIL }) #NOTE(topol) #for extra debugging uncomment the following line #ldap.set_option(ldap.OPT_DEBUG_LEVEL, 4095) using_ldaps = url.lower().startswith("ldaps") if use_tls and using_ldaps: raise AssertionError(_('Invalid TLS / LDAPS combination')) if use_tls: if not ldap.TLS_AVAIL: raise ValueError(_('Invalid LDAP TLS_AVAIL option: %s. TLS ' 'not available') % ldap.TLS_AVAIL) if tls_cacertfile: #NOTE(topol) #python ldap TLS does not verify CACERTFILE or CACERTDIR #so we add some extra simple sanity check verification #Also, setting these values globally (i.e. on the ldap object) #works but these values are ignored when setting them on the #connection if not os.path.isfile(tls_cacertfile): raise IOError(_("tls_cacertfile %s not found " "or is not a file") % tls_cacertfile) ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, tls_cacertfile) elif tls_cacertdir: #NOTE(topol) #python ldap TLS does not verify CACERTFILE or CACERTDIR #so we add some extra simple sanity check verification #Also, setting these values globally (i.e. on the ldap object) #works but these values are ignored when setting them on the #connection if not os.path.isdir(tls_cacertdir): raise IOError(_("tls_cacertdir %s not found " "or is not a directory") % tls_cacertdir) ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, tls_cacertdir) if tls_req_cert in LDAP_TLS_CERTS.values(): ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_req_cert) else: LOG.debug(_("LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s"), tls_req_cert) self.conn = ldap.initialize(url) self.conn.protocol_version = ldap.VERSION3 if alias_dereferencing is not None: self.conn.set_option(ldap.OPT_DEREF, alias_dereferencing) self.page_size = page_size if use_tls: self.conn.start_tls_s() if chase_referrals is not None: self.conn.set_option(ldap.OPT_REFERRALS, int(chase_referrals)) def simple_bind_s(self, user, password): LOG.debug(_("LDAP bind: dn=%s"), user) return self.conn.simple_bind_s(user, password) def unbind_s(self): LOG.debug("LDAP unbind") return self.conn.unbind_s() def add_s(self, dn, attrs): ldap_attrs = [(kind, [py2ldap(x) for x in safe_iter(values)]) for kind, values in attrs] sane_attrs = [(kind, values if kind != 'userPassword' else ['****']) for kind, values in ldap_attrs] LOG.debug(_('LDAP add: dn=%(dn)s, attrs=%(attrs)s'), { 'dn': dn, 'attrs': sane_attrs}) return self.conn.add_s(dn, ldap_attrs) def search_s(self, dn, scope, query, attrlist=None): # NOTE(morganfainberg): Remove "None" singletons from this list, which # allows us to set mapped attributes to "None" as defaults in config. # Without this filtering, the ldap query would raise a TypeError since # attrlist is expected to be an iterable of strings. if attrlist is not None: attrlist = [attr for attr in attrlist if attr is not None] LOG.debug(_( 'LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, ' 'attrs=%(attrlist)s'), { 'dn': dn, 'scope': scope, 'query': query, 'attrlist': attrlist}) if self.page_size: res = self.paged_search_s(dn, scope, query, attrlist) else: res = self.conn.search_s(dn, scope, query, attrlist) o = [] at_least_one_referral = False for dn, attrs in res: if dn is None: # this is a Referral object, rather than an Entry object at_least_one_referral = True continue o.append((dn, dict((kind, [ldap2py(x) for x in values]) for kind, values in six.iteritems(attrs)))) if at_least_one_referral: LOG.debug(_('Referrals were returned and ignored. Enable referral ' 'chasing in keystone.conf via [ldap] chase_referrals')) return o def paged_search_s(self, dn, scope, query, attrlist=None): res = [] lc = ldap.controls.SimplePagedResultsControl( controlType=ldap.LDAP_CONTROL_PAGE_OID, criticality=True, controlValue=(self.page_size, '')) msgid = self.conn.search_ext(dn, scope, query, attrlist, serverctrls=[lc]) # Endless loop request pages on ldap server until it has no data while True: # Request to the ldap server a page with 'page_size' entries rtype, rdata, rmsgid, serverctrls = self.conn.result3(msgid) # Receive the data res.extend(rdata) pctrls = [c for c in serverctrls if c.controlType == ldap.LDAP_CONTROL_PAGE_OID] if pctrls: # LDAP server supports pagination est, cookie = pctrls[0].controlValue if cookie: # There is more data still on the server # so we request another page lc.controlValue = (self.page_size, cookie) msgid = self.conn.search_ext(dn, scope, query, attrlist, serverctrls=[lc]) else: # Exit condition no more data on server break else: LOG.warning(_('LDAP Server does not support paging. ' 'Disable paging in keystone.conf to ' 'avoid this message.')) self._disable_paging() break return res def modify_s(self, dn, modlist): ldap_modlist = [ (op, kind, (None if values is None else [py2ldap(x) for x in safe_iter(values)])) for op, kind, values in modlist] sane_modlist = [(op, kind, (values if kind != 'userPassword' else ['****'])) for op, kind, values in ldap_modlist] LOG.debug(_('LDAP modify: dn=%(dn)s, modlist=%(modlist)s'), { 'dn': dn, 'modlist': sane_modlist}) return self.conn.modify_s(dn, ldap_modlist) def delete_s(self, dn): LOG.debug(_("LDAP delete: dn=%s"), dn) return self.conn.delete_s(dn) def delete_ext_s(self, dn, serverctrls): LOG.debug( _('LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s'), { 'dn': dn, 'serverctrls': serverctrls}) return self.conn.delete_ext_s(dn, serverctrls) def _disable_paging(self): # Disable the pagination from now on self.page_size = 0 class EnabledEmuMixIn(BaseLdap): """Emulates boolean 'enabled' attribute if turned on. Creates groupOfNames holding all enabled objects of this class, all missing objects are considered disabled. Options: * $name_enabled_emulation - boolean, on/off * $name_enabled_emulation_dn - DN of that groupOfNames, default is cn=enabled_${name}s,${tree_dn} Where ${name}s is the plural of self.options_name ('users' or 'tenants'), ${tree_dn} is self.tree_dn. """ def __init__(self, conf): super(EnabledEmuMixIn, self).__init__(conf) enabled_emulation = '%s_enabled_emulation' % self.options_name self.enabled_emulation = getattr(conf.ldap, enabled_emulation) enabled_emulation_dn = '%s_enabled_emulation_dn' % self.options_name self.enabled_emulation_dn = getattr(conf.ldap, enabled_emulation_dn) if not self.enabled_emulation_dn: self.enabled_emulation_dn = ('cn=enabled_%ss,%s' % (self.options_name, self.tree_dn)) def _get_enabled(self, object_id): conn = self.get_connection() dn = self._id_to_dn(object_id) query = '(member=%s)' % dn try: enabled_value = conn.search_s(self.enabled_emulation_dn, ldap.SCOPE_BASE, query, ['cn']) except ldap.NO_SUCH_OBJECT: return False else: return bool(enabled_value) finally: conn.unbind_s() def _add_enabled(self, object_id): if not self._get_enabled(object_id): conn = self.get_connection() modlist = [(ldap.MOD_ADD, 'member', [self._id_to_dn(object_id)])] try: conn.modify_s(self.enabled_emulation_dn, modlist) except ldap.NO_SUCH_OBJECT: attr_list = [('objectClass', ['groupOfNames']), ('member', [self._id_to_dn(object_id)])] if self.use_dumb_member: attr_list[1][1].append(self.dumb_member) conn.add_s(self.enabled_emulation_dn, attr_list) finally: conn.unbind_s() def _remove_enabled(self, object_id): conn = self.get_connection() modlist = [(ldap.MOD_DELETE, 'member', [self._id_to_dn(object_id)])] try: conn.modify_s(self.enabled_emulation_dn, modlist) except (ldap.NO_SUCH_OBJECT, ldap.NO_SUCH_ATTRIBUTE): pass finally: conn.unbind_s() def create(self, values): if self.enabled_emulation: enabled_value = values.pop('enabled', True) ref = super(EnabledEmuMixIn, self).create(values) if 'enabled' not in self.attribute_ignore: if enabled_value: self._add_enabled(ref['id']) ref['enabled'] = enabled_value return ref else: return super(EnabledEmuMixIn, self).create(values) def get(self, object_id, ldap_filter=None): ref = super(EnabledEmuMixIn, self).get(object_id, ldap_filter) if 'enabled' not in self.attribute_ignore and self.enabled_emulation: ref['enabled'] = self._get_enabled(object_id) return ref def get_all(self, ldap_filter=None): if 'enabled' not in self.attribute_ignore and self.enabled_emulation: # had to copy BaseLdap.get_all here to ldap_filter by DN tenant_list = [self._ldap_res_to_model(x) for x in self._ldap_get_all(ldap_filter) if x[0] != self.enabled_emulation_dn] for tenant_ref in tenant_list: tenant_ref['enabled'] = self._get_enabled(tenant_ref['id']) return tenant_list else: return super(EnabledEmuMixIn, self).get_all(ldap_filter) def update(self, object_id, values, old_obj=None): if 'enabled' not in self.attribute_ignore and self.enabled_emulation: data = values.copy() enabled_value = data.pop('enabled', None) ref = super(EnabledEmuMixIn, self).update(object_id, data, old_obj) if enabled_value is not None: if enabled_value: self._add_enabled(object_id) else: self._remove_enabled(object_id) return ref else: return super(EnabledEmuMixIn, self).update( object_id, values, old_obj) def delete(self, object_id): if self.enabled_emulation: self._remove_enabled(object_id) super(EnabledEmuMixIn, self).delete(object_id) keystone-2014.1/keystone/common/ldap/__init__.py0000664000175400017540000000120212323716272022762 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.common.ldap.core import * keystone-2014.1/keystone/credential/0000775000175400017540000000000012323716511020554 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/credential/controllers.py0000664000175400017540000001045212323716267023506 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import hashlib import json from keystone.common import controller from keystone.common import dependency from keystone.common import driver_hints from keystone import exception from keystone.openstack.common.gettextutils import _ @dependency.requires('credential_api') class CredentialV3(controller.V3Controller): collection_name = 'credentials' member_name = 'credential' def __init__(self): super(CredentialV3, self).__init__() self.get_member_from_driver = self.credential_api.get_credential def _assign_unique_id(self, ref, trust_id=None): # Generates and assigns a unique identifer to # a credential reference. if ref.get('type', '').lower() == 'ec2': try: blob = json.loads(ref.get('blob')) except (ValueError, TypeError): raise exception.ValidationError( message=_('Invalid blob in credential')) if not blob or not isinstance(blob, dict): raise exception.ValidationError(attribute='blob', target='credential') if blob.get('access') is None: raise exception.ValidationError(attribute='access', target='blob') ret_ref = ref.copy() ret_ref['id'] = hashlib.sha256(blob['access']).hexdigest() # Update the blob with the trust_id, so credentials created # with a trust scoped token will result in trust scoped # tokens when authentication via ec2tokens happens if trust_id is not None: blob['trust_id'] = trust_id ret_ref['blob'] = json.dumps(blob) return ret_ref else: return super(CredentialV3, self)._assign_unique_id(ref) @controller.protected() def create_credential(self, context, credential): trust_id = self._get_trust_id_for_request(context) ref = self._assign_unique_id(self._normalize_dict(credential), trust_id) ref = self.credential_api.create_credential(ref['id'], ref) return CredentialV3.wrap_member(context, ref) @staticmethod def _blob_to_json(ref): # credentials stored via ec2tokens before the fix for #1259584 # need json serializing, as that's the documented API format blob = ref.get('blob') if isinstance(blob, dict): new_ref = ref.copy() new_ref['blob'] = json.dumps(blob) return new_ref else: return ref @controller.protected() def list_credentials(self, context): # NOTE(henry-nash): Since there are no filters for credentials, we # shouldn't limit the output, hence we don't pass a hints list into # the driver. refs = self.credential_api.list_credentials() ret_refs = [self._blob_to_json(r) for r in refs] return CredentialV3.wrap_collection(context, ret_refs, driver_hints.Hints()) @controller.protected() def get_credential(self, context, credential_id): ref = self.credential_api.get_credential(credential_id) ret_ref = self._blob_to_json(ref) return CredentialV3.wrap_member(context, ret_ref) @controller.protected() def update_credential(self, context, credential_id, credential): self._require_matching_id(credential_id, credential) ref = self.credential_api.update_credential(credential_id, credential) return CredentialV3.wrap_member(context, ref) @controller.protected() def delete_credential(self, context, credential_id): return self.credential_api.delete_credential(credential_id) keystone-2014.1/keystone/credential/core.py0000664000175400017540000000712412323716267022072 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Main entry point into the Credentials service.""" import abc import six from keystone.common import dependency from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) @dependency.provider('credential_api') class Manager(manager.Manager): """Default pivot point for the Credential backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.credential.driver) @six.add_metaclass(abc.ABCMeta) class Driver(object): # credential crud @abc.abstractmethod def create_credential(self, credential_id, credential): """Creates a new credential. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_credentials(self, **filters): """List all credentials in the system applying filters. :returns: a list of credential_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_credential(self, credential_id): """Get a credential by ID. :returns: credential_ref :raises: keystone.exception.CredentialNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_credential(self, credential_id, credential): """Updates an existing credential. :raises: keystone.exception.CredentialNotFound, keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def delete_credential(self, credential_id): """Deletes an existing credential. :raises: keystone.exception.CredentialNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_credentials_for_project(self, project_id): """Deletes all credentials for a project.""" self._delete_credentials(lambda cr: cr['project_id'] == project_id) @abc.abstractmethod def delete_credentials_for_user(self, user_id): """Deletes all credentials for a user.""" self._delete_credentials(lambda cr: cr['user_id'] == user_id) def _delete_credentials(self, match_fn): """Do the actual credential deletion work (default implementation). :param match_fn: function that takes a credential dict as the parameter and returns true or false if the identifier matches the credential dict. """ for cr in self.list_credentials(): if match_fn(cr): try: self.credential_api.delete_credential(cr['id']) except exception.CredentialNotFound: LOG.debug(_('Deletion of credential is not required: %s'), cr['id']) keystone-2014.1/keystone/credential/routers.py0000664000175400017540000000155612323716267022650 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """WSGI Routers for the Credentials service.""" from keystone.common import router from keystone.credential import controllers def append_v3_routers(mapper, routers): routers.append( router.Router(controllers.CredentialV3(), 'credentials', 'credential')) keystone-2014.1/keystone/credential/backends/0000775000175400017540000000000012323716511022326 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/credential/backends/sql.py0000664000175400017540000000750612323716272023513 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import sql from keystone.common.sql import migration_helpers from keystone import credential from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration class CredentialModel(sql.ModelBase, sql.DictBase): __tablename__ = 'credential' attributes = ['id', 'user_id', 'project_id', 'blob', 'type'] id = sql.Column(sql.String(64), primary_key=True) user_id = sql.Column(sql.String(64), nullable=False) project_id = sql.Column(sql.String(64)) blob = sql.Column(sql.JsonBlob(), nullable=False) type = sql.Column(sql.String(255), nullable=False) extra = sql.Column(sql.JsonBlob()) class Credential(credential.Driver): # Internal interface to manage the database def db_sync(self, version=None): migration.db_sync( sql.get_engine(), migration_helpers.find_migrate_repo(), version=version) # credential crud @sql.handle_conflicts(conflict_type='credential') def create_credential(self, credential_id, credential): session = sql.get_session() with session.begin(): ref = CredentialModel.from_dict(credential) session.add(ref) return ref.to_dict() def list_credentials(self, **filters): session = sql.get_session() query = session.query(CredentialModel) if 'user_id' in filters: query = query.filter_by(user_id=filters.get('user_id')) refs = query.all() return [ref.to_dict() for ref in refs] def _get_credential(self, session, credential_id): ref = session.query(CredentialModel).get(credential_id) if ref is None: raise exception.CredentialNotFound(credential_id=credential_id) return ref def get_credential(self, credential_id): session = sql.get_session() return self._get_credential(session, credential_id).to_dict() @sql.handle_conflicts(conflict_type='credential') def update_credential(self, credential_id, credential): session = sql.get_session() with session.begin(): ref = self._get_credential(session, credential_id) old_dict = ref.to_dict() for k in credential: old_dict[k] = credential[k] new_credential = CredentialModel.from_dict(old_dict) for attr in CredentialModel.attributes: if attr != 'id': setattr(ref, attr, getattr(new_credential, attr)) ref.extra = new_credential.extra return ref.to_dict() def delete_credential(self, credential_id): session = sql.get_session() with session.begin(): ref = self._get_credential(session, credential_id) session.delete(ref) def delete_credentials_for_project(self, project_id): session = sql.get_session() with session.begin(): query = session.query(CredentialModel) query = query.filter_by(project_id=project_id) query.delete() def delete_credentials_for_user(self, user_id): session = sql.get_session() with session.begin(): query = session.query(CredentialModel) query = query.filter_by(user_id=user_id) query.delete() keystone-2014.1/keystone/credential/backends/__init__.py0000664000175400017540000000000012323716267024435 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/credential/__init__.py0000664000175400017540000000132512323716272022672 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2013 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. from keystone.credential import controllers from keystone.credential.core import * from keystone.credential import routers keystone-2014.1/keystone/notifications.py0000664000175400017540000002556212323716267021707 0ustar jenkinsjenkins00000000000000# Copyright 2013 IBM Corp. # # 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. """Notifications module for OpenStack Identity Service resources""" import logging import socket from oslo.config import cfg from oslo import messaging import pycadf from pycadf import cadftaxonomy as taxonomy from pycadf import cadftype from pycadf import eventfactory from pycadf import resource from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log notifier_opts = [ cfg.StrOpt('default_publisher_id', default=None, help='Default publisher_id for outgoing notifications'), ] LOG = log.getLogger(__name__) # NOTE(gyee): actions that can be notified. One must update this list whenever # a new action is supported. ACTIONS = frozenset(['created', 'deleted', 'disabled', 'updated']) # resource types that can be notified SUBSCRIBERS = {} _notifier = None CONF = cfg.CONF CONF.register_opts(notifier_opts) class ManagerNotificationWrapper(object): """Send event notifications for ``Manager`` methods. Sends a notification if the wrapped Manager method does not raise an ``Exception`` (such as ``keystone.exception.NotFound``). :param operation: one of the values from ACTIONS :param resource_type: type of resource being affected :param public: If True (default), the event will be sent to the notifier API. If False, the event will only be sent via notify_event_callbacks to in process listeners """ def __init__(self, operation, resource_type, public=True, resource_id_arg_index=1): self.operation = operation self.resource_type = resource_type self.public = public self.resource_id_arg_index = resource_id_arg_index def __call__(self, f): def wrapper(*args, **kwargs): """Send a notification if the wrapped callable is successful.""" try: result = f(*args, **kwargs) except Exception: raise else: resource_id = args[self.resource_id_arg_index] _send_notification( self.operation, self.resource_type, resource_id, public=self.public) return result return wrapper def created(*args, **kwargs): """Decorator to send notifications for ``Manager.create_*`` methods.""" return ManagerNotificationWrapper('created', *args, **kwargs) def updated(*args, **kwargs): """Decorator to send notifications for ``Manager.update_*`` methods.""" return ManagerNotificationWrapper('updated', *args, **kwargs) def disabled(*args, **kwargs): """Decorator to send notifications when an object is disabled.""" return ManagerNotificationWrapper('disabled', *args, **kwargs) def deleted(*args, **kwargs): """Decorator to send notifications for ``Manager.delete_*`` methods.""" return ManagerNotificationWrapper('deleted', *args, **kwargs) def _get_callback_info(callback): if getattr(callback, 'im_class', None): return [getattr(callback, '__module__', None), callback.im_class.__name__, callback.__name__] else: return [getattr(callback, '__module__', None), callback.__name__] def register_event_callback(event, resource_type, callbacks): if event not in ACTIONS: raise ValueError(_('%(event)s is not a valid notification event, must ' 'be one of: %(actions)s') % {'event': event, 'actions': ', '.join(ACTIONS)}) if not hasattr(callbacks, '__iter__'): callbacks = [callbacks] for callback in callbacks: if not callable(callback): msg = _('Method not callable: %s') % callback LOG.error(msg) raise TypeError(msg) SUBSCRIBERS.setdefault(event, {}).setdefault(resource_type, set()) SUBSCRIBERS[event][resource_type].add(callback) if LOG.logger.getEffectiveLevel() <= logging.INFO: # Do this only if its going to appear in the logs. msg = _('Callback: `%(callback)s` subscribed to event ' '`%(event)s`.') callback_info = _get_callback_info(callback) callback_str = '.'.join(i for i in callback_info if i is not None) event_str = '.'.join(['identity', resource_type, event]) LOG.info(msg, {'callback': callback_str, 'event': event_str}) def notify_event_callbacks(service, resource_type, operation, payload): """Sends a notification to registered extensions.""" if operation in SUBSCRIBERS: if resource_type in SUBSCRIBERS[operation]: for cb in SUBSCRIBERS[operation][resource_type]: subst_dict = {'cb_name': cb.__name__, 'service': service, 'resource_type': resource_type, 'operation': operation, 'payload': payload} LOG.debug(_('Invoking callback %(cb_name)s for event ' '%(service)s %(resource_type)s %(operation)s for' '%(payload)s'), subst_dict) cb(service, resource_type, operation, payload) def _get_notifier(): """Return a notifier object. If _notifier is None it means that a notifier object has not been set. If _notifier is False it means that a notifier has previously failed to construct. Otherwise it is a constructed Notifier object. """ global _notifier if _notifier is None: host = CONF.default_publisher_id or socket.gethostname() try: transport = messaging.get_transport(CONF) _notifier = messaging.Notifier(transport, "identity.%s" % host) except Exception: LOG.exception("Failed to construct notifier") _notifier = False return _notifier def _reset_notifier(): global _notifier _notifier = None def _send_notification(operation, resource_type, resource_id, public=True): """Send notification to inform observers about the affected resource. This method doesn't raise an exception when sending the notification fails. :param operation: operation being performed (created, updated, or deleted) :param resource_type: type of resource being operated on :param resource_id: ID of resource being operated on :param public: if True (default), the event will be sent to the notifier API. if False, the event will only be sent via notify_event_callbacks to in process listeners. """ context = {} payload = {'resource_info': resource_id} service = 'identity' event_type = '%(service)s.%(resource_type)s.%(operation)s' % { 'service': service, 'resource_type': resource_type, 'operation': operation} notify_event_callbacks(service, resource_type, operation, payload) if public: notifier = _get_notifier() if notifier: try: notifier.info(context, event_type, payload) except Exception: LOG.exception(_( 'Failed to send %(res_id)s %(event_type)s notification'), {'res_id': resource_id, 'event_type': event_type}) class CadfNotificationWrapper(object): """Send CADF event notifications for various methods. Sends CADF notifications for events such as whether an authentication was successful or not. """ def __init__(self, action): self.action = action def __call__(self, f): def wrapper(wrapped_self, context, user_id, *args, **kwargs): """Always send a notification.""" remote_addr = None http_user_agent = None environment = context.get('environment') if environment: remote_addr = environment.get('REMOTE_ADDR') http_user_agent = environment.get('HTTP_USER_AGENT') host = pycadf.host.Host(address=remote_addr, agent=http_user_agent) initiator = resource.Resource(typeURI=taxonomy.ACCOUNT_USER, name=user_id, host=host) _send_audit_notification(self.action, initiator, taxonomy.OUTCOME_PENDING) try: result = f(wrapped_self, context, user_id, *args, **kwargs) except Exception: # For authentication failure send a cadf event as well _send_audit_notification(self.action, initiator, taxonomy.OUTCOME_FAILURE) raise else: _send_audit_notification(self.action, initiator, taxonomy.OUTCOME_SUCCESS) return result return wrapper def _send_audit_notification(action, initiator, outcome): """Send CADF notification to inform observers about the affected resource. This method logs an exception when sending the notification fails. :param action: CADF action being audited (e.g., 'authenticate') :param initiator: CADF resource representing the initiator :param outcome: The CADF outcome (taxonomy.OUTCOME_PENDING, taxonomy.OUTCOME_SUCCESS, taxonomy.OUTCOME_FAILURE) """ event = eventfactory.EventFactory().new_event( eventType=cadftype.EVENTTYPE_ACTIVITY, outcome=outcome, action=action, initiator=initiator, target=resource.Resource(typeURI=taxonomy.ACCOUNT_USER), observer=resource.Resource(typeURI='service/security')) context = {} payload = event.as_dict() LOG.debug(_('CADF Event: %s'), payload) service = 'identity' event_type = '%(service)s.%(action)s' % {'service': service, 'action': action} notifier = _get_notifier() if notifier: try: notifier.info(context, event_type, payload) except Exception: # diaper defense: any exception that occurs while emitting the # notification should not interfere with the API request LOG.exception(_( 'Failed to send %(action)s %(event_type)s notification'), {'action': action, 'event_type': event_type}) emit_event = CadfNotificationWrapper keystone-2014.1/keystone/token/0000775000175400017540000000000012323716511017562 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/token/providers/0000775000175400017540000000000012323716511021577 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/token/providers/uuid.py0000664000175400017540000000164112323716267023131 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Keystone UUID Token Provider""" from __future__ import absolute_import import uuid from keystone.token.providers import common class Provider(common.BaseProvider): def __init__(self, *args, **kwargs): super(Provider, self).__init__(*args, **kwargs) def _get_token_id(self, token_data): return uuid.uuid4().hex keystone-2014.1/keystone/token/providers/common.py0000664000175400017540000007046612323716272023462 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import json import sys import six from six.moves.urllib import parse from keystone.common import dependency from keystone import config from keystone.contrib import federation from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone import token from keystone.token import provider from keystone import trust from keystone.openstack.common import log from keystone.openstack.common import timeutils LOG = log.getLogger(__name__) CONF = config.CONF class V2TokenDataHelper(object): """Creates V2 token data.""" @classmethod def format_token(cls, token_ref, roles_ref=None, catalog_ref=None): user_ref = token_ref['user'] metadata_ref = token_ref['metadata'] if roles_ref is None: roles_ref = [] expires = token_ref.get('expires', token.default_expire_time()) if expires is not None: if not isinstance(expires, six.text_type): expires = timeutils.isotime(expires) o = {'access': {'token': {'id': token_ref['id'], 'expires': expires, 'issued_at': timeutils.strtime() }, 'user': {'id': user_ref['id'], 'name': user_ref['name'], 'username': user_ref['name'], 'roles': roles_ref, 'roles_links': metadata_ref.get('roles_links', []) } } } if 'bind' in token_ref: o['access']['token']['bind'] = token_ref['bind'] if 'tenant' in token_ref and token_ref['tenant']: token_ref['tenant']['enabled'] = True o['access']['token']['tenant'] = token_ref['tenant'] if catalog_ref is not None: o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog( catalog_ref) if metadata_ref: if 'is_admin' in metadata_ref: o['access']['metadata'] = {'is_admin': metadata_ref['is_admin']} else: o['access']['metadata'] = {'is_admin': 0} if 'roles' in metadata_ref: o['access']['metadata']['roles'] = metadata_ref['roles'] if CONF.trust.enabled and 'trust_id' in metadata_ref: o['access']['trust'] = {'trustee_user_id': metadata_ref['trustee_user_id'], 'id': metadata_ref['trust_id'] } return o @classmethod def format_catalog(cls, catalog_ref): """Munge catalogs from internal to output format Internal catalogs look like:: {$REGION: { {$SERVICE: { $key1: $value1, ... } } } The legacy api wants them to look like:: [{'name': $SERVICE[name], 'type': $SERVICE, 'endpoints': [{ 'tenantId': $tenant_id, ... 'region': $REGION, }], 'endpoints_links': [], }] """ if not catalog_ref: return [] services = {} for region, region_ref in six.iteritems(catalog_ref): for service, service_ref in six.iteritems(region_ref): new_service_ref = services.get(service, {}) new_service_ref['name'] = service_ref.pop('name') new_service_ref['type'] = service new_service_ref['endpoints_links'] = [] service_ref['region'] = region endpoints_ref = new_service_ref.get('endpoints', []) endpoints_ref.append(service_ref) new_service_ref['endpoints'] = endpoints_ref services[service] = new_service_ref return services.values() @dependency.requires('assignment_api', 'catalog_api', 'identity_api', 'trust_api') class V3TokenDataHelper(object): """Token data helper.""" def __init__(self): if CONF.trust.enabled: self.trust_api = trust.Manager() def _get_filtered_domain(self, domain_id): domain_ref = self.assignment_api.get_domain(domain_id) return {'id': domain_ref['id'], 'name': domain_ref['name']} def _get_filtered_project(self, project_id): project_ref = self.assignment_api.get_project(project_id) filtered_project = { 'id': project_ref['id'], 'name': project_ref['name']} filtered_project['domain'] = self._get_filtered_domain( project_ref['domain_id']) return filtered_project def _populate_scope(self, token_data, domain_id, project_id): if 'domain' in token_data or 'project' in token_data: # scope already exist, no need to populate it again return if domain_id: token_data['domain'] = self._get_filtered_domain(domain_id) if project_id: token_data['project'] = self._get_filtered_project(project_id) def _get_roles_for_user(self, user_id, domain_id, project_id): roles = [] if domain_id: roles = self.assignment_api.get_roles_for_user_and_domain( user_id, domain_id) if project_id: roles = self.assignment_api.get_roles_for_user_and_project( user_id, project_id) return [self.assignment_api.get_role(role_id) for role_id in roles] def _populate_roles_for_groups(self, group_ids, project_id=None, domain_id=None, user_id=None): def _check_roles(roles, user_id, project_id, domain_id): # User was granted roles so simply exit this function. if roles: return if project_id: msg = _('User %(user_id)s has no access ' 'to project %(project_id)s') % { 'user_id': user_id, 'project_id': project_id} elif domain_id: msg = _('User %(user_id)s has no access ' 'to domain %(domain_id)s') % { 'user_id': user_id, 'domain_id': domain_id} # Since no roles were found a user is not authorized to # perform any operations. Raise an exception with # appropriate error message. raise exception.Unauthorized(msg) roles = self.assignment_api.get_roles_for_groups(group_ids, project_id, domain_id) _check_roles(roles, user_id, project_id, domain_id) return roles def _populate_user(self, token_data, user_id, trust): if 'user' in token_data: # no need to repopulate user if it already exists return user_ref = self.identity_api.get_user(user_id) if CONF.trust.enabled and trust and 'OS-TRUST:trust' not in token_data: trustor_user_ref = (self.identity_api.get_user( trust['trustor_user_id'])) if not trustor_user_ref['enabled']: raise exception.Forbidden(_('Trustor is disabled.')) if trust['impersonation']: user_ref = trustor_user_ref token_data['OS-TRUST:trust'] = ( { 'id': trust['id'], 'trustor_user': {'id': trust['trustor_user_id']}, 'trustee_user': {'id': trust['trustee_user_id']}, 'impersonation': trust['impersonation'] }) filtered_user = { 'id': user_ref['id'], 'name': user_ref['name'], 'domain': self._get_filtered_domain(user_ref['domain_id'])} token_data['user'] = filtered_user def _populate_oauth_section(self, token_data, access_token): if access_token: access_token_id = access_token['id'] consumer_id = access_token['consumer_id'] token_data['OS-OAUTH1'] = ({'access_token_id': access_token_id, 'consumer_id': consumer_id}) def _populate_roles(self, token_data, user_id, domain_id, project_id, trust, access_token): if 'roles' in token_data: # no need to repopulate roles return if access_token: filtered_roles = [] authed_role_ids = json.loads(access_token['role_ids']) all_roles = self.assignment_api.list_roles() for role in all_roles: for authed_role in authed_role_ids: if authed_role == role['id']: filtered_roles.append({'id': role['id'], 'name': role['name']}) token_data['roles'] = filtered_roles return if CONF.trust.enabled and trust: token_user_id = trust['trustor_user_id'] token_project_id = trust['project_id'] #trusts do not support domains yet token_domain_id = None else: token_user_id = user_id token_project_id = project_id token_domain_id = domain_id if token_domain_id or token_project_id: roles = self._get_roles_for_user(token_user_id, token_domain_id, token_project_id) filtered_roles = [] if CONF.trust.enabled and trust: for trust_role in trust['roles']: match_roles = [x for x in roles if x['id'] == trust_role['id']] if match_roles: filtered_roles.append(match_roles[0]) else: raise exception.Forbidden( _('Trustee has no delegated roles.')) else: for role in roles: filtered_roles.append({'id': role['id'], 'name': role['name']}) # user has no project or domain roles, therefore access denied if not filtered_roles: if token_project_id: msg = _('User %(user_id)s has no access ' 'to project %(project_id)s') % { 'user_id': user_id, 'project_id': token_project_id} else: msg = _('User %(user_id)s has no access ' 'to domain %(domain_id)s') % { 'user_id': user_id, 'domain_id': token_domain_id} LOG.debug(msg) raise exception.Unauthorized(msg) token_data['roles'] = filtered_roles def _populate_service_catalog(self, token_data, user_id, domain_id, project_id, trust): if 'catalog' in token_data: # no need to repopulate service catalog return if CONF.trust.enabled and trust: user_id = trust['trustor_user_id'] if project_id or domain_id: try: service_catalog = self.catalog_api.get_v3_catalog( user_id, project_id) except exception.NotImplemented: service_catalog = {} # TODO(gyee): v3 service catalog is not quite completed yet # TODO(ayoung): Enforce Endpoints for trust token_data['catalog'] = service_catalog def _populate_token_dates(self, token_data, expires=None, trust=None): if not expires: expires = token.default_expire_time() if not isinstance(expires, six.string_types): expires = timeutils.isotime(expires, subsecond=True) token_data['expires_at'] = expires token_data['issued_at'] = timeutils.isotime(subsecond=True) def get_token_data(self, user_id, method_names, extras, domain_id=None, project_id=None, expires=None, trust=None, token=None, include_catalog=True, bind=None, access_token=None): token_data = {'methods': method_names, 'extras': extras} # We've probably already written these to the token if token: for x in ('roles', 'user', 'catalog', 'project', 'domain'): if x in token: token_data[x] = token[x] if CONF.trust.enabled and trust: if user_id != trust['trustee_user_id']: raise exception.Forbidden(_('User is not a trustee.')) if bind: token_data['bind'] = bind self._populate_scope(token_data, domain_id, project_id) self._populate_user(token_data, user_id, trust) self._populate_roles(token_data, user_id, domain_id, project_id, trust, access_token) if include_catalog: self._populate_service_catalog(token_data, user_id, domain_id, project_id, trust) self._populate_token_dates(token_data, expires=expires, trust=trust) self._populate_oauth_section(token_data, access_token) return {'token': token_data} @dependency.optional('oauth_api', 'revoke_api') @dependency.requires('assignment_api', 'catalog_api', 'identity_api', 'token_api', 'trust_api') class BaseProvider(provider.Provider): def __init__(self, *args, **kwargs): super(BaseProvider, self).__init__(*args, **kwargs) if CONF.trust.enabled: self.trust_api = trust.Manager() self.v3_token_data_helper = V3TokenDataHelper() self.v2_token_data_helper = V2TokenDataHelper() def get_token_version(self, token_data): if token_data and isinstance(token_data, dict): if 'token_version' in token_data: if token_data['token_version'] in token.provider.VERSIONS: return token_data['token_version'] # FIXME(morganfainberg): deprecate the following logic in future # revisions. It is better to just specify the token_version in # the token_data itself. This way we can support future versions # that might have the same fields. if 'access' in token_data: return token.provider.V2 if 'token' in token_data and 'methods' in token_data['token']: return token.provider.V3 raise token.provider.UnsupportedTokenVersionException() def issue_v2_token(self, token_ref, roles_ref=None, catalog_ref=None): token_data = self.v2_token_data_helper.format_token( token_ref, roles_ref, catalog_ref) token_id = self._get_token_id(token_data) token_data['access']['token']['id'] = token_id try: expiry = token_data['access']['token']['expires'] if isinstance(expiry, six.string_types): expiry = timeutils.normalize_time( timeutils.parse_isotime(expiry)) data = dict(key=token_id, id=token_id, expires=expiry, user=token_ref['user'], tenant=token_ref['tenant'], metadata=token_ref['metadata'], token_data=token_data, bind=token_ref.get('bind'), trust_id=token_ref['metadata'].get('trust_id'), token_version=token.provider.V2) self.token_api.create_token(token_id, data) except Exception: exc_info = sys.exc_info() # an identical token may have been created already. # if so, return the token_data as it is also identical try: self.token_api.get_token(token_id) except exception.TokenNotFound: raise exc_info[0], exc_info[1], exc_info[2] return (token_id, token_data) def issue_v3_token(self, user_id, method_names, expires_at=None, project_id=None, domain_id=None, auth_context=None, trust=None, metadata_ref=None, include_catalog=True): # for V2, trust is stashed in metadata_ref if (CONF.trust.enabled and not trust and metadata_ref and 'trust_id' in metadata_ref): trust = self.trust_api.get_trust(metadata_ref['trust_id']) token_ref = None if 'saml2' in method_names: token_ref = self._handle_saml2_tokens(auth_context, project_id, domain_id) access_token = None if 'oauth1' in method_names: if self.oauth_api: access_token_id = auth_context['access_token_id'] access_token = self.oauth_api.get_access_token(access_token_id) else: raise exception.Forbidden(_('Oauth is disabled.')) token_data = self.v3_token_data_helper.get_token_data( user_id, method_names, auth_context.get('extras') if auth_context else None, domain_id=domain_id, project_id=project_id, expires=expires_at, trust=trust, bind=auth_context.get('bind') if auth_context else None, token=token_ref, include_catalog=include_catalog, access_token=access_token) token_id = self._get_token_id(token_data) try: expiry = token_data['token']['expires_at'] if isinstance(expiry, six.string_types): expiry = timeutils.normalize_time( timeutils.parse_isotime(expiry)) # FIXME(gyee): is there really a need to store roles in metadata? role_ids = [] if metadata_ref is None: metadata_ref = {} if 'project' in token_data['token']: # project-scoped token, fill in the v2 token data # all we care are the role IDs role_ids = [r['id'] for r in token_data['token']['roles']] metadata_ref = {'roles': role_ids} if trust: metadata_ref.setdefault('trust_id', trust['id']) metadata_ref.setdefault('trustee_user_id', trust['trustee_user_id']) data = dict(key=token_id, id=token_id, expires=expiry, user=token_data['token']['user'], tenant=token_data['token'].get('project'), metadata=metadata_ref, token_data=token_data, trust_id=trust['id'] if trust else None, token_version=token.provider.V3) self.token_api.create_token(token_id, data) except Exception: exc_info = sys.exc_info() # an identical token may have been created already. # if so, return the token_data as it is also identical try: self.token_api.get_token(token_id) except exception.TokenNotFound: raise exc_info[0], exc_info[1], exc_info[2] return (token_id, token_data) def _handle_saml2_tokens(self, auth_context, project_id, domain_id): user_id = auth_context['user_id'] group_ids = auth_context['group_ids'] token_data = { 'user': { 'id': user_id, 'name': parse.unquote(user_id) } } if project_id or domain_id: roles = self.v3_token_data_helper._populate_roles_for_groups( group_ids, project_id, domain_id, user_id) token_data.update({'roles': roles}) else: idp = auth_context[federation.IDENTITY_PROVIDER] protocol = auth_context[federation.PROTOCOL] token_data['user'].update({ federation.FEDERATION: { 'identity_provider': {'id': idp}, 'protocol': {'id': protocol}, 'groups': [{'id': x} for x in group_ids] }, }) return token_data def _verify_token(self, token_id): """Verify the given token and return the token_ref.""" token_ref = self.token_api.get_token(token_id) return self._verify_token_ref(token_ref) def _verify_token_ref(self, token_ref): """Verify and return the given token_ref.""" if not token_ref: raise exception.Unauthorized() return token_ref def revoke_token(self, token_id): token = self.token_api.get_token(token_id) if self.revoke_api: version = self.get_token_version(token) if version == provider.V3: user_id = token['user']['id'] expires_at = token['expires'] elif version == provider.V2: user_id = token['user_id'] expires_at = token['expires'] self.revoke_api.revoke_by_expiration(user_id, expires_at) if CONF.token.revoke_by_id: self.token_api.delete_token(token_id=token_id) def _assert_default_domain(self, token_ref): """Make sure we are operating on default domain only.""" if (token_ref.get('token_data') and self.get_token_version(token_ref.get('token_data')) == token.provider.V3): # this is a V3 token msg = _('Non-default domain is not supported') # user in a non-default is prohibited if (token_ref['token_data']['token']['user']['domain']['id'] != CONF.identity.default_domain_id): raise exception.Unauthorized(msg) # domain scoping is prohibited if token_ref['token_data']['token'].get('domain'): raise exception.Unauthorized( _('Domain scoped token is not supported')) # project in non-default domain is prohibited if token_ref['token_data']['token'].get('project'): project = token_ref['token_data']['token']['project'] project_domain_id = project['domain']['id'] # scoped to project in non-default domain is prohibited if project_domain_id != CONF.identity.default_domain_id: raise exception.Unauthorized(msg) # if token is scoped to trust, both trustor and trustee must # be in the default domain. Furthermore, the delegated project # must also be in the default domain metadata_ref = token_ref['metadata'] if CONF.trust.enabled and 'trust_id' in metadata_ref: trust_ref = self.trust_api.get_trust(metadata_ref['trust_id']) trustee_user_ref = self.identity_api.get_user( trust_ref['trustee_user_id']) if (trustee_user_ref['domain_id'] != CONF.identity.default_domain_id): raise exception.Unauthorized(msg) trustor_user_ref = self.identity_api.get_user( trust_ref['trustor_user_id']) if (trustor_user_ref['domain_id'] != CONF.identity.default_domain_id): raise exception.Unauthorized(msg) project_ref = self.assignment_api.get_project( trust_ref['project_id']) if (project_ref['domain_id'] != CONF.identity.default_domain_id): raise exception.Unauthorized(msg) def validate_v2_token(self, token_id): token_ref = self._verify_token(token_id) return self._validate_v2_token_ref(token_ref) def _validate_v2_token_ref(self, token_ref): try: self._assert_default_domain(token_ref) # FIXME(gyee): performance or correctness? Should we return the # cached token or reconstruct it? Obviously if we are going with # the cached token, any role, project, or domain name changes # will not be reflected. One may argue that with PKI tokens, # we are essentially doing cached token validation anyway. # Lets go with the cached token strategy. Since token # management layer is now pluggable, one can always provide # their own implementation to suit their needs. token_data = token_ref.get('token_data') if (not token_data or self.get_token_version(token_data) != token.provider.V2): # token is created by old v2 logic metadata_ref = token_ref['metadata'] roles_ref = [] for role_id in metadata_ref.get('roles', []): roles_ref.append(self.assignment_api.get_role(role_id)) # Get a service catalog if possible # This is needed for on-behalf-of requests catalog_ref = None if token_ref.get('tenant'): catalog_ref = self.catalog_api.get_catalog( token_ref['user']['id'], token_ref['tenant']['id'], metadata_ref) token_data = self.v2_token_data_helper.format_token( token_ref, roles_ref, catalog_ref) return token_data except exception.ValidationError as e: LOG.exception(_('Failed to validate token')) raise exception.TokenNotFound(e) def validate_v3_token(self, token_id): try: token_ref = self._verify_token(token_id) token_data = self._validate_v3_token_ref(token_ref) return token_data except (exception.ValidationError, exception.UserNotFound): raise exception.TokenNotFound(token_id) def _validate_v3_token_ref(self, token_ref): # FIXME(gyee): performance or correctness? Should we return the # cached token or reconstruct it? Obviously if we are going with # the cached token, any role, project, or domain name changes # will not be reflected. One may argue that with PKI tokens, # we are essentially doing cached token validation anyway. # Lets go with the cached token strategy. Since token # management layer is now pluggable, one can always provide # their own implementation to suit their needs. token_data = token_ref.get('token_data') if not token_data or 'token' not in token_data: # token ref is created by V2 API project_id = None project_ref = token_ref.get('tenant') if project_ref: project_id = project_ref['id'] token_data = self.v3_token_data_helper.get_token_data( token_ref['user']['id'], ['password', 'token'], {}, project_id=project_id, bind=token_ref.get('bind'), expires=token_ref['expires']) return token_data def validate_token(self, token_id): token_ref = self._verify_token(token_id) version = self.get_token_version(token_ref) if version == token.provider.V3: return self._validate_v3_token_ref(token_ref) elif version == token.provider.V2: return self._validate_v2_token_ref(token_ref) raise token.provider.UnsupportedTokenVersionException() keystone-2014.1/keystone/token/providers/pki.py0000664000175400017540000000270712323716267022752 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Keystone PKI Token Provider""" import json from keystoneclient.common import cms from keystone.common import environment from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.token.providers import common CONF = config.CONF LOG = log.getLogger(__name__) class Provider(common.BaseProvider): def _get_token_id(self, token_data): try: token_id = cms.cms_sign_token(json.dumps(token_data), CONF.signing.certfile, CONF.signing.keyfile) return token_id except environment.subprocess.CalledProcessError: LOG.exception(_('Unable to sign token')) raise exception.UnexpectedError(_( 'Unable to sign token.')) keystone-2014.1/keystone/token/providers/__init__.py0000664000175400017540000000000012323716267023706 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/token/controllers.py0000664000175400017540000004454612323716272022523 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import datetime import json from keystoneclient.common import cms import six from keystone.common import controller from keystone.common import dependency from keystone.common import wsgi from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils from keystone.token import core CONF = config.CONF LOG = log.getLogger(__name__) class ExternalAuthNotApplicable(Exception): """External authentication is not applicable.""" pass @dependency.requires('assignment_api', 'catalog_api', 'identity_api', 'token_api', 'token_provider_api', 'trust_api') class Auth(controller.V2Controller): @controller.v2_deprecated def ca_cert(self, context, auth=None): ca_file = open(CONF.signing.ca_certs, 'r') data = ca_file.read() ca_file.close() return data @controller.v2_deprecated def signing_cert(self, context, auth=None): cert_file = open(CONF.signing.certfile, 'r') data = cert_file.read() cert_file.close() return data @controller.v2_deprecated def authenticate(self, context, auth=None): """Authenticate credentials and return a token. Accept auth as a dict that looks like:: { "auth":{ "passwordCredentials":{ "username":"test_user", "password":"mypass" }, "tenantName":"customer-x" } } In this case, tenant is optional, if not provided the token will be considered "unscoped" and can later be used to get a scoped token. Alternatively, this call accepts auth with only a token and tenant that will return a token that is scoped to that tenant. """ if auth is None: raise exception.ValidationError(attribute='auth', target='request body') if "token" in auth: # Try to authenticate using a token auth_info = self._authenticate_token( context, auth) else: # Try external authentication try: auth_info = self._authenticate_external( context, auth) except ExternalAuthNotApplicable: # Try local authentication auth_info = self._authenticate_local( context, auth) user_ref, tenant_ref, metadata_ref, expiry, bind = auth_info core.validate_auth_info(self, user_ref, tenant_ref) # NOTE(morganfainberg): Make sure the data is in correct form since it # might be consumed external to Keystone and this is a v2.0 controller. # The user_ref is encoded into the auth_token_data which is returned as # part of the token data. The token provider doesn't care about the # format. user_ref = self.v3_to_v2_user(user_ref) if tenant_ref: tenant_ref = self.filter_domain_id(tenant_ref) auth_token_data = self._get_auth_token_data(user_ref, tenant_ref, metadata_ref, expiry) if tenant_ref: catalog_ref = self.catalog_api.get_catalog( user_ref['id'], tenant_ref['id'], metadata_ref) else: catalog_ref = {} auth_token_data['id'] = 'placeholder' if bind: auth_token_data['bind'] = bind roles_ref = [] for role_id in metadata_ref.get('roles', []): role_ref = self.assignment_api.get_role(role_id) roles_ref.append(dict(name=role_ref['name'])) (token_id, token_data) = self.token_provider_api.issue_v2_token( auth_token_data, roles_ref=roles_ref, catalog_ref=catalog_ref) return token_data def _authenticate_token(self, context, auth): """Try to authenticate using an already existing token. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'token' not in auth: raise exception.ValidationError( attribute='token', target='auth') if "id" not in auth['token']: raise exception.ValidationError( attribute="id", target="token") old_token = auth['token']['id'] if len(old_token) > CONF.max_token_size: raise exception.ValidationSizeError(attribute='token', size=CONF.max_token_size) try: old_token_ref = self.token_api.get_token(old_token) except exception.NotFound as e: raise exception.Unauthorized(e) wsgi.validate_token_bind(context, old_token_ref) #A trust token cannot be used to get another token if 'trust' in old_token_ref: raise exception.Forbidden() if 'trust_id' in old_token_ref['metadata']: raise exception.Forbidden() user_ref = old_token_ref['user'] user_id = user_ref['id'] if not CONF.trust.enabled and 'trust_id' in auth: raise exception.Forbidden('Trusts are disabled.') elif CONF.trust.enabled and 'trust_id' in auth: trust_ref = self.trust_api.get_trust(auth['trust_id']) if trust_ref is None: raise exception.Forbidden() if user_id != trust_ref['trustee_user_id']: raise exception.Forbidden() if ('expires' in trust_ref) and (trust_ref['expires']): expiry = trust_ref['expires'] if expiry < timeutils.parse_isotime(timeutils.isotime()): raise exception.Forbidden()() user_id = trust_ref['trustor_user_id'] trustor_user_ref = self.identity_api.get_user( trust_ref['trustor_user_id']) if not trustor_user_ref['enabled']: raise exception.Forbidden()() trustee_user_ref = self.identity_api.get_user( trust_ref['trustee_user_id']) if not trustee_user_ref['enabled']: raise exception.Forbidden()() self.trust_api.consume_use(auth['trust_id']) if trust_ref['impersonation'] is True: current_user_ref = trustor_user_ref else: current_user_ref = trustee_user_ref else: current_user_ref = self.identity_api.get_user(user_id) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = old_token_ref['expires'] if CONF.trust.enabled and 'trust_id' in auth: trust_id = auth['trust_id'] trust_roles = [] for role in trust_ref['roles']: if 'roles' not in metadata_ref: raise exception.Forbidden()() if role['id'] in metadata_ref['roles']: trust_roles.append(role['id']) else: raise exception.Forbidden() if 'expiry' in trust_ref and trust_ref['expiry']: trust_expiry = timeutils.parse_isotime(trust_ref['expiry']) if trust_expiry < expiry: expiry = trust_expiry metadata_ref['roles'] = trust_roles metadata_ref['trustee_user_id'] = trust_ref['trustee_user_id'] metadata_ref['trust_id'] = trust_id bind = old_token_ref.get('bind') return (current_user_ref, tenant_ref, metadata_ref, expiry, bind) def _authenticate_local(self, context, auth): """Try to authenticate against the identity backend. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'passwordCredentials' not in auth: raise exception.ValidationError( attribute='passwordCredentials', target='auth') if "password" not in auth['passwordCredentials']: raise exception.ValidationError( attribute='password', target='passwordCredentials') password = auth['passwordCredentials']['password'] if password and len(password) > CONF.identity.max_password_length: raise exception.ValidationSizeError( attribute='password', size=CONF.identity.max_password_length) if ("userId" not in auth['passwordCredentials'] and "username" not in auth['passwordCredentials']): raise exception.ValidationError( attribute='username or userId', target='passwordCredentials') user_id = auth['passwordCredentials'].get('userId') if user_id and len(user_id) > CONF.max_param_size: raise exception.ValidationSizeError(attribute='userId', size=CONF.max_param_size) username = auth['passwordCredentials'].get('username', '') if len(username) > CONF.max_param_size: raise exception.ValidationSizeError(attribute='username', size=CONF.max_param_size) if username: try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) try: user_ref = self.identity_api.authenticate( context, user_id=user_id, password=password) except AssertionError as e: raise exception.Unauthorized(e.args[0]) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = core.default_expire_time() return (user_ref, tenant_ref, metadata_ref, expiry, None) def _authenticate_external(self, context, auth): """Try to authenticate an external user via REMOTE_USER variable. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'REMOTE_USER' not in context.get('environment', {}): raise ExternalAuthNotApplicable() #NOTE(jamielennox): xml and json differ and get confused about what # empty auth should look like so just reset it. if not auth: auth = {} username = context['environment']['REMOTE_USER'] try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = core.default_expire_time() bind = None if ('kerberos' in CONF.token.bind and context['environment']. get('AUTH_TYPE', '').lower() == 'negotiate'): bind = {'kerberos': username} return (user_ref, tenant_ref, metadata_ref, expiry, bind) def _get_auth_token_data(self, user, tenant, metadata, expiry): return dict(user=user, tenant=tenant, metadata=metadata, expires=expiry) def _get_project_id_from_auth(self, auth): """Extract tenant information from auth dict. Returns a valid tenant_id if it exists, or None if not specified. """ tenant_id = auth.get('tenantId') if tenant_id and len(tenant_id) > CONF.max_param_size: raise exception.ValidationSizeError(attribute='tenantId', size=CONF.max_param_size) tenant_name = auth.get('tenantName') if tenant_name and len(tenant_name) > CONF.max_param_size: raise exception.ValidationSizeError(attribute='tenantName', size=CONF.max_param_size) if tenant_name: try: tenant_ref = self.assignment_api.get_project_by_name( tenant_name, CONF.identity.default_domain_id) tenant_id = tenant_ref['id'] except exception.ProjectNotFound as e: raise exception.Unauthorized(e) return tenant_id def _get_project_roles_and_ref(self, user_id, tenant_id): """Returns the project roles for this user, and the project ref.""" tenant_ref = None role_list = [] if tenant_id: try: tenant_ref = self.assignment_api.get_project(tenant_id) role_list = self.assignment_api.get_roles_for_user_and_project( user_id, tenant_id) except exception.ProjectNotFound: pass if not role_list: msg = _('User %(u_id)s is unauthorized for tenant %(t_id)s') msg = msg % {'u_id': user_id, 't_id': tenant_id} LOG.warning(msg) raise exception.Unauthorized(msg) return (tenant_ref, role_list) def _get_token_ref(self, token_id, belongs_to=None): """Returns a token if a valid one exists. Optionally, limited to a token owned by a specific tenant. """ data = self.token_api.get_token(token_id) if belongs_to: if data.get('tenant') is None: raise exception.Unauthorized( _('Token does not belong to specified tenant.')) if data['tenant'].get('id') != belongs_to: raise exception.Unauthorized( _('Token does not belong to specified tenant.')) return data @controller.v2_deprecated @controller.protected() def validate_token_head(self, context, token_id): """Check that a token is valid. Optionally, also ensure that it is owned by a specific tenant. Identical to ``validate_token``, except does not return a response. """ # TODO(ayoung) validate against revocation API belongs_to = context['query_string'].get('belongsTo') self.token_provider_api.check_v2_token(token_id, belongs_to) @controller.v2_deprecated @controller.protected() def validate_token(self, context, token_id): """Check that a token is valid. Optionally, also ensure that it is owned by a specific tenant. Returns metadata about the token along any associated roles. """ belongs_to = context['query_string'].get('belongsTo') # TODO(ayoung) validate against revocation API return self.token_provider_api.validate_v2_token(token_id, belongs_to) @controller.v2_deprecated def delete_token(self, context, token_id): """Delete a token, effectively invalidating it for authz.""" # TODO(termie): this stuff should probably be moved to middleware self.assert_admin(context) self.token_provider_api.revoke_token(token_id) @controller.v2_deprecated @controller.protected() def revocation_list(self, context, auth=None): if not CONF.token.revoke_by_id: raise exception.Gone() tokens = self.token_api.list_revoked_tokens() for t in tokens: expires = t['expires'] if expires and isinstance(expires, datetime.datetime): t['expires'] = timeutils.isotime(expires) data = {'revoked': tokens} json_data = json.dumps(data) signed_text = cms.cms_sign_text(json_data, CONF.signing.certfile, CONF.signing.keyfile) return {'signed': signed_text} @controller.v2_deprecated def endpoints(self, context, token_id): """Return a list of endpoints available to the token.""" self.assert_admin(context) token_ref = self._get_token_ref(token_id) catalog_ref = None if token_ref.get('tenant'): catalog_ref = self.catalog_api.get_catalog( token_ref['user']['id'], token_ref['tenant']['id'], token_ref['metadata']) return Auth.format_endpoint_list(catalog_ref) @classmethod def format_endpoint_list(cls, catalog_ref): """Formats a list of endpoints according to Identity API v2. The v2.0 API wants an endpoint list to look like:: { 'endpoints': [ { 'id': $endpoint_id, 'name': $SERVICE[name], 'type': $SERVICE, 'tenantId': $tenant_id, 'region': $REGION, } ], 'endpoints_links': [], } """ if not catalog_ref: return {} endpoints = [] for region_name, region_ref in six.iteritems(catalog_ref): for service_type, service_ref in six.iteritems(region_ref): endpoints.append({ 'id': service_ref.get('id'), 'name': service_ref.get('name'), 'type': service_type, 'region': region_name, 'publicURL': service_ref.get('publicURL'), 'internalURL': service_ref.get('internalURL'), 'adminURL': service_ref.get('adminURL'), }) return {'endpoints': endpoints, 'endpoints_links': []} keystone-2014.1/keystone/token/core.py0000664000175400017540000003702412323716267021102 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Main entry point into the Token service.""" import abc import copy import datetime from keystoneclient.common import cms import six from keystone.common import cache from keystone.common import dependency from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils from keystone.openstack.common import versionutils CONF = config.CONF LOG = log.getLogger(__name__) SHOULD_CACHE = cache.should_cache_fn('token') # NOTE(blk-u): The config options are not available at import time. EXPIRATION_TIME = lambda: CONF.token.cache_time REVOCATION_CACHE_EXPIRATION_TIME = lambda: CONF.token.revocation_cache_time def default_expire_time(): """Determine when a fresh token should expire. Expiration time varies based on configuration (see ``[token] expiration``). :returns: a naive UTC datetime.datetime object """ expire_delta = datetime.timedelta(seconds=CONF.token.expiration) return timeutils.utcnow() + expire_delta def validate_auth_info(self, user_ref, tenant_ref): """Validate user and tenant auth info. Validate the user and tenant auth info in order to ensure that user and tenant information is valid and not disabled. Consolidate the checks here to ensure consistency between token auth and ec2 auth. :params user_ref: the authenticating user :params tenant_ref: the scope of authorization, if any :raises Unauthorized: if any of the user, user's domain, tenant or tenant's domain are either disabled or otherwise invalid """ # If the user is disabled don't allow them to authenticate if not user_ref.get('enabled', True): msg = _('User is disabled: %s') % user_ref['id'] LOG.warning(msg) raise exception.Unauthorized(msg) # If the user's domain is disabled don't allow them to authenticate user_domain_ref = self.assignment_api.get_domain( user_ref['domain_id']) if user_domain_ref and not user_domain_ref.get('enabled', True): msg = _('Domain is disabled: %s') % user_domain_ref['id'] LOG.warning(msg) raise exception.Unauthorized(msg) if tenant_ref: # If the project is disabled don't allow them to authenticate if not tenant_ref.get('enabled', True): msg = _('Tenant is disabled: %s') % tenant_ref['id'] LOG.warning(msg) raise exception.Unauthorized(msg) # If the project's domain is disabled don't allow them to authenticate project_domain_ref = self.assignment_api.get_domain( tenant_ref['domain_id']) if (project_domain_ref and not project_domain_ref.get('enabled', True)): msg = _('Domain is disabled: %s') % project_domain_ref['id'] LOG.warning(msg) raise exception.Unauthorized(msg) @dependency.requires('assignment_api', 'identity_api', 'token_provider_api', 'trust_api') @dependency.provider('token_api') class Manager(manager.Manager): """Default pivot point for the Token backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.token.driver) def unique_id(self, token_id): """Return a unique ID for a token. The returned value is useful as the primary key of a database table, memcache store, or other lookup table. :returns: Given a PKI token, returns it's hashed value. Otherwise, returns the passed-in value (such as a UUID token ID or an existing hash). """ return cms.cms_hash_token(token_id) def _assert_valid(self, token_id, token_ref): """Raise TokenNotFound if the token is expired.""" current_time = timeutils.normalize_time(timeutils.utcnow()) expires = token_ref.get('expires') if not expires or current_time > timeutils.normalize_time(expires): raise exception.TokenNotFound(token_id=token_id) def get_token(self, token_id): if not token_id: # NOTE(morganfainberg): There are cases when the # context['token_id'] will in-fact be None. This also saves # a round-trip to the backend if we don't have a token_id. raise exception.TokenNotFound(token_id='') unique_id = self.unique_id(token_id) token_ref = self._get_token(unique_id) # NOTE(morganfainberg): Lift expired checking to the manager, there is # no reason to make the drivers implement this check. With caching, # self._get_token could return an expired token. Make sure we behave # as expected and raise TokenNotFound on those instances. self._assert_valid(token_id, token_ref) return token_ref @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def _get_token(self, token_id): # Only ever use the "unique" id in the cache key. return self.driver.get_token(token_id) def create_token(self, token_id, data): unique_id = self.unique_id(token_id) data_copy = copy.deepcopy(data) data_copy['id'] = unique_id ret = self.driver.create_token(unique_id, data_copy) if SHOULD_CACHE(ret): # NOTE(morganfainberg): when doing a cache set, you must pass the # same arguments through, the same as invalidate (this includes # "self"). First argument is always the value to be cached self._get_token.set(ret, self, unique_id) return ret def delete_token(self, token_id): if not CONF.token.revoke_by_id: return unique_id = self.unique_id(token_id) self.driver.delete_token(unique_id) self._invalidate_individual_token_cache(unique_id) self.invalidate_revocation_list() def delete_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): if not CONF.token.revoke_by_id: return token_list = self.driver._list_tokens(user_id, tenant_id, trust_id, consumer_id) self.driver.delete_tokens(user_id, tenant_id, trust_id, consumer_id) for token_id in token_list: unique_id = self.unique_id(token_id) self._invalidate_individual_token_cache(unique_id) self.invalidate_revocation_list() @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=REVOCATION_CACHE_EXPIRATION_TIME) def list_revoked_tokens(self): return self.driver.list_revoked_tokens() def invalidate_revocation_list(self): # NOTE(morganfainberg): Note that ``self`` needs to be passed to # invalidate() because of the way the invalidation method works on # determining cache-keys. self.list_revoked_tokens.invalidate(self) def delete_tokens_for_domain(self, domain_id): """Delete all tokens for a given domain.""" if not CONF.token.revoke_by_id: return projects = self.assignment_api.list_projects() for project in projects: if project['domain_id'] == domain_id: for user_id in self.assignment_api.list_user_ids_for_project( project['id']): self.delete_tokens_for_user(user_id, project['id']) # TODO(morganfainberg): implement deletion of domain_scoped tokens. def delete_tokens_for_user(self, user_id, project_id=None): """Delete all tokens for a given user or user-project combination. This method adds in the extra logic for handling trust-scoped token revocations in a single call instead of needing to explicitly handle trusts in the caller's logic. """ if not CONF.token.revoke_by_id: return self.delete_tokens(user_id, tenant_id=project_id) for trust in self.trust_api.list_trusts_for_trustee(user_id): # Ensure we revoke tokens associated to the trust / project # user_id combination. self.delete_tokens(user_id, trust_id=trust['id'], tenant_id=project_id) for trust in self.trust_api.list_trusts_for_trustor(user_id): # Ensure we revoke tokens associated to the trust / project / # user_id combination where the user_id is the trustor. # NOTE(morganfainberg): This revocation is a bit coarse, but it # covers a number of cases such as disabling of the trustor user, # deletion of the trustor user (for any number of reasons). It # might make sense to refine this and be more surgical on the # deletions (e.g. don't revoke tokens for the trusts when the # trustor changes password). For now, to maintain previous # functionality, this will continue to be a bit overzealous on # revocations. self.delete_tokens(trust['trustee_user_id'], trust_id=trust['id'], tenant_id=project_id) def delete_tokens_for_users(self, user_ids, project_id=None): """Delete all tokens for a list of user_ids. :param user_ids: list of user identifiers :param project_id: optional project identifier """ if not CONF.token.revoke_by_id: return for user_id in user_ids: self.delete_tokens_for_user(user_id, project_id=project_id) def _invalidate_individual_token_cache(self, token_id): # NOTE(morganfainberg): invalidate takes the exact same arguments as # the normal method, this means we need to pass "self" in (which gets # stripped off). # FIXME(morganfainberg): Does this cache actually need to be # invalidated? We maintain a cached revocation list, which should be # consulted before accepting a token as valid. For now we will # do the explicit individual token invalidation. self._get_token.invalidate(self, token_id) self.token_provider_api.invalidate_individual_token_cache(token_id) @versionutils.deprecated(versionutils.deprecated.ICEHOUSE, remove_in=+1) def list_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): """Returns a list of current token_id's for a user This is effectively a private method only used by the ``delete_tokens`` method and should not be called by anything outside of the ``token_api`` manager or the token driver itself. :param user_id: identity of the user :type user_id: string :param tenant_id: identity of the tenant :type tenant_id: string :param trust_id: identity of the trust :type trust_id: string :param consumer_id: identity of the consumer :type consumer_id: string :returns: list of token_id's """ return self.driver._list_tokens(user_id, tenant_id=tenant_id, trust_id=trust_id, consumer_id=consumer_id) @six.add_metaclass(abc.ABCMeta) class Driver(object): """Interface description for a Token driver.""" @abc.abstractmethod def get_token(self, token_id): """Get a token by id. :param token_id: identity of the token :type token_id: string :returns: token_ref :raises: keystone.exception.TokenNotFound """ raise exception.NotImplemented() @abc.abstractmethod def create_token(self, token_id, data): """Create a token by id and data. :param token_id: identity of the token :type token_id: string :param data: dictionary with additional reference information :: { expires='' id=token_id, user=user_ref, tenant=tenant_ref, metadata=metadata_ref } :type data: dict :returns: token_ref or None. """ raise exception.NotImplemented() @abc.abstractmethod def delete_token(self, token_id): """Deletes a token by id. :param token_id: identity of the token :type token_id: string :returns: None. :raises: keystone.exception.TokenNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): """Deletes tokens by user. If the tenant_id is not None, only delete the tokens by user id under the specified tenant. If the trust_id is not None, it will be used to query tokens and the user_id will be ignored. If the consumer_id is not None, only delete the tokens by consumer id that match the specified consumer id. :param user_id: identity of user :type user_id: string :param tenant_id: identity of the tenant :type tenant_id: string :param trust_id: identity of the trust :type trust_id: string :param consumer_id: identity of the consumer :type consumer_id: string :returns: None. :raises: keystone.exception.TokenNotFound """ if not CONF.token.revoke_by_id: return token_list = self._list_tokens(user_id, tenant_id=tenant_id, trust_id=trust_id, consumer_id=consumer_id) for token in token_list: try: self.delete_token(token) except exception.NotFound: pass @abc.abstractmethod def _list_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): """Returns a list of current token_id's for a user This is effectively a private method only used by the ``delete_tokens`` method and should not be called by anything outside of the ``token_api`` manager or the token driver itself. :param user_id: identity of the user :type user_id: string :param tenant_id: identity of the tenant :type tenant_id: string :param trust_id: identity of the trust :type trust_id: string :param consumer_id: identity of the consumer :type consumer_id: string :returns: list of token_id's """ raise exception.NotImplemented() @abc.abstractmethod def list_revoked_tokens(self): """Returns a list of all revoked tokens :returns: list of token_id's """ raise exception.NotImplemented() @abc.abstractmethod def flush_expired_tokens(self): """Archive or delete tokens that have expired. """ raise exception.NotImplemented() keystone-2014.1/keystone/token/routers.py0000664000175400017540000000457212323716267021657 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import wsgi from keystone.token import controllers class Router(wsgi.ComposableRouter): def add_routes(self, mapper): token_controller = controllers.Auth() mapper.connect('/tokens', controller=token_controller, action='authenticate', conditions=dict(method=['POST'])) mapper.connect('/tokens/revoked', controller=token_controller, action='revocation_list', conditions=dict(method=['GET'])) mapper.connect('/tokens/{token_id}', controller=token_controller, action='validate_token', conditions=dict(method=['GET'])) mapper.connect('/tokens/{token_id}', controller=token_controller, action='validate_token_head', conditions=dict(method=['HEAD'])) mapper.connect('/tokens/{token_id}', controller=token_controller, action='delete_token', conditions=dict(method=['DELETE'])) mapper.connect('/tokens/{token_id}/endpoints', controller=token_controller, action='endpoints', conditions=dict(method=['GET'])) # Certificates used to verify auth tokens mapper.connect('/certificates/ca', controller=token_controller, action='ca_cert', conditions=dict(method=['GET'])) mapper.connect('/certificates/signing', controller=token_controller, action='signing_cert', conditions=dict(method=['GET'])) keystone-2014.1/keystone/token/backends/0000775000175400017540000000000012323716511021334 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/token/backends/sql.py0000664000175400017540000002141712323716267022522 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import copy from keystone.common import sql from keystone import config from keystone import exception from keystone.openstack.common import timeutils from keystone import token CONF = config.CONF class TokenModel(sql.ModelBase, sql.DictBase): __tablename__ = 'token' attributes = ['id', 'expires', 'user_id', 'trust_id'] id = sql.Column(sql.String(64), primary_key=True) expires = sql.Column(sql.DateTime(), default=None) extra = sql.Column(sql.JsonBlob()) valid = sql.Column(sql.Boolean(), default=True, nullable=False) user_id = sql.Column(sql.String(64)) trust_id = sql.Column(sql.String(64)) __table_args__ = ( sql.Index('ix_token_expires', 'expires'), sql.Index('ix_token_expires_valid', 'expires', 'valid') ) class Token(token.Driver): # Public interface def get_token(self, token_id): if token_id is None: raise exception.TokenNotFound(token_id=token_id) session = sql.get_session() token_ref = session.query(TokenModel).get(token_id) if not token_ref or not token_ref.valid: raise exception.TokenNotFound(token_id=token_id) return token_ref.to_dict() def create_token(self, token_id, data): data_copy = copy.deepcopy(data) if not data_copy.get('expires'): data_copy['expires'] = token.default_expire_time() if not data_copy.get('user_id'): data_copy['user_id'] = data_copy['user']['id'] token_ref = TokenModel.from_dict(data_copy) token_ref.valid = True session = sql.get_session() with session.begin(): session.add(token_ref) return token_ref.to_dict() def delete_token(self, token_id): session = sql.get_session() with session.begin(): token_ref = session.query(TokenModel).get(token_id) if not token_ref or not token_ref.valid: raise exception.TokenNotFound(token_id=token_id) token_ref.valid = False def delete_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): """Deletes all tokens in one session The user_id will be ignored if the trust_id is specified. user_id will always be specified. If using a trust, the token's user_id is set to the trustee's user ID or the trustor's user ID, so will use trust_id to query the tokens. """ session = sql.get_session() with session.begin(): now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter_by(valid=True) query = query.filter(TokenModel.expires > now) if trust_id: query = query.filter(TokenModel.trust_id == trust_id) else: query = query.filter(TokenModel.user_id == user_id) for token_ref in query.all(): if tenant_id: token_ref_dict = token_ref.to_dict() if not self._tenant_matches(tenant_id, token_ref_dict): continue if consumer_id: token_ref_dict = token_ref.to_dict() if not self._consumer_matches(consumer_id, token_ref_dict): continue token_ref.valid = False def _tenant_matches(self, tenant_id, token_ref_dict): return ((tenant_id is None) or (token_ref_dict.get('tenant') and token_ref_dict['tenant'].get('id') == tenant_id)) def _consumer_matches(self, consumer_id, ref): if consumer_id is None: return True else: try: oauth = ref['token_data']['token'].get('OS-OAUTH1', {}) return oauth and oauth['consumer_id'] == consumer_id except KeyError: return False def _list_tokens_for_trust(self, trust_id): session = sql.get_session() tokens = [] now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter(TokenModel.expires > now) query = query.filter(TokenModel.trust_id == trust_id) token_references = query.filter_by(valid=True) for token_ref in token_references: token_ref_dict = token_ref.to_dict() tokens.append(token_ref_dict['id']) return tokens def _list_tokens_for_user(self, user_id, tenant_id=None): session = sql.get_session() tokens = [] now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter(TokenModel.expires > now) query = query.filter(TokenModel.user_id == user_id) token_references = query.filter_by(valid=True) for token_ref in token_references: token_ref_dict = token_ref.to_dict() if self._tenant_matches(tenant_id, token_ref_dict): tokens.append(token_ref['id']) return tokens def _list_tokens_for_consumer(self, user_id, consumer_id): tokens = [] session = sql.get_session() with session.begin(): now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter(TokenModel.expires > now) query = query.filter(TokenModel.user_id == user_id) token_references = query.filter_by(valid=True) for token_ref in token_references: token_ref_dict = token_ref.to_dict() if self._consumer_matches(consumer_id, token_ref_dict): tokens.append(token_ref_dict['id']) return tokens def _list_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): if not CONF.token.revoke_by_id: return [] if trust_id: return self._list_tokens_for_trust(trust_id) if consumer_id: return self._list_tokens_for_consumer(user_id, consumer_id) else: return self._list_tokens_for_user(user_id, tenant_id) def list_revoked_tokens(self): session = sql.get_session() tokens = [] now = timeutils.utcnow() query = session.query(TokenModel.id, TokenModel.expires) query = query.filter(TokenModel.expires > now) token_references = query.filter_by(valid=False) for token_ref in token_references: record = { 'id': token_ref[0], 'expires': token_ref[1], } tokens.append(record) return tokens def token_flush_batch_size(self, dialect): batch_size = 0 if dialect == 'ibm_db_sa': # This functionality is limited to DB2, because # it is necessary to prevent the tranaction log # from filling up, whereas at least some of the # other supported databases do not support update # queries with LIMIT subqueries nor do they appear # to require the use of such queries when deleting # large numbers of records at once. batch_size = 100 # Limit of 100 is known to not fill a transaction log # of default maximum size while not significantly # impacting the performance of large token purges on # systems where the maximum transaction log size has # been increased beyond the default. return batch_size def flush_expired_tokens(self): session = sql.get_session() dialect = session.bind.dialect.name batch_size = self.token_flush_batch_size(dialect) if batch_size > 0: query = session.query(TokenModel.id) query = query.filter(TokenModel.expires < timeutils.utcnow()) query = query.limit(batch_size).subquery() delete_query = (session.query(TokenModel). filter(TokenModel.id.in_(query))) while True: rowcount = delete_query.delete(synchronize_session=False) if rowcount == 0: break else: query = session.query(TokenModel) query = query.filter(TokenModel.expires < timeutils.utcnow()) query.delete(synchronize_session=False) session.flush() keystone-2014.1/keystone/token/backends/memcache.py0000664000175400017540000000206012323716267023456 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, Inc. # Copyright 2012 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. from keystone.common import config from keystone.token.backends import kvs CONF = config.CONF class Token(kvs.Token): kvs_backend = 'openstack.kvs.Memcached' def __init__(self, *args, **kwargs): kwargs['no_expiry_keys'] = [self.revocation_key] kwargs['memcached_expire_time'] = CONF.token.expiration kwargs['url'] = CONF.memcache.servers super(Token, self).__init__(*args, **kwargs) keystone-2014.1/keystone/token/backends/kvs.py0000664000175400017540000003503712323716267022531 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, Inc. # Copyright 2012 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. from __future__ import absolute_import import copy import six from keystone.common import kvs from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils from keystone import token CONF = config.CONF LOG = log.getLogger(__name__) class Token(token.Driver): """KeyValueStore backend for tokens. This is the base implementation for any/all key-value-stores (e.g. memcached) for the Token backend. It is recommended to only use the base in-memory implementation for testing purposes. """ revocation_key = 'revocation-list' kvs_backend = 'openstack.kvs.Memory' def __init__(self, backing_store=None, **kwargs): super(Token, self).__init__() self._store = kvs.get_key_value_store('token-driver') if backing_store is not None: self.kvs_backend = backing_store self._store.configure(backing_store=self.kvs_backend, **kwargs) if self.__class__ == Token: # NOTE(morganfainberg): Only warn if the base KVS implementation # is instantiated. LOG.warn(_('It is recommended to only use the base ' 'key-value-store implementation for the token driver ' 'for testing purposes. ' 'Please use keystone.token.backends.memcache.Token ' 'or keystone.token.backends.sql.Token instead.')) def _prefix_token_id(self, token_id): return 'token-%s' % token_id.encode('utf-8') def _prefix_user_id(self, user_id): return 'usertokens-%s' % user_id.encode('utf-8') def _get_key_or_default(self, key, default=None): try: return self._store.get(key) except exception.NotFound: return default def _get_key(self, key): return self._store.get(key) def _set_key(self, key, value, lock=None): self._store.set(key, value, lock) def _delete_key(self, key): return self._store.delete(key) def get_token(self, token_id): ptk = self._prefix_token_id(token_id) try: token_ref = self._get_key(ptk) except exception.NotFound: raise exception.TokenNotFound(token_id=token_id) return token_ref def create_token(self, token_id, data): """Create a token by id and data. It is assumed the caller has performed data validation on the "data" parameter. """ data_copy = copy.deepcopy(data) ptk = self._prefix_token_id(token_id) if not data_copy.get('expires'): data_copy['expires'] = token.default_expire_time() if not data_copy.get('user_id'): data_copy['user_id'] = data_copy['user']['id'] # NOTE(morganfainberg): for ease of manipulating the data without # concern about the backend, always store the value(s) in the # index as the isotime (string) version so this is where the string is # built. expires_str = timeutils.isotime(data_copy['expires'], subsecond=True) self._set_key(ptk, data_copy) user_id = data['user']['id'] user_key = self._prefix_user_id(user_id) self._update_user_token_list(user_key, token_id, expires_str) if CONF.trust.enabled and data.get('trust_id'): # NOTE(morganfainberg): If trusts are enabled and this is a trust # scoped token, we add the token to the trustee list as well. This # allows password changes of the trustee to also expire the token. # There is no harm in placing the token in multiple lists, as # _list_tokens is smart enough to handle almost any case of # valid/invalid/expired for a given token. token_data = data_copy['token_data'] if data_copy['token_version'] == token.provider.V2: trustee_user_id = token_data['access']['trust'][ 'trustee_user_id'] elif data_copy['token_version'] == token.provider.V3: trustee_user_id = token_data['OS-TRUST:trust'][ 'trustee_user_id'] else: raise token.provider.UnsupportedTokenVersionException( _('Unknown token version %s') % data_copy.get('token_version')) trustee_key = self._prefix_user_id(trustee_user_id) self._update_user_token_list(trustee_key, token_id, expires_str) return data_copy def _get_user_token_list_with_expiry(self, user_key): """Return a list of tuples in the format (token_id, token_expiry) for the user_key. """ return self._get_key_or_default(user_key, default=[]) def _get_user_token_list(self, user_key): """Return a list of token_ids for the user_key.""" token_list = self._get_user_token_list_with_expiry(user_key) # Each element is a tuple of (token_id, token_expiry). Most code does # not care about the expiry, it is stripped out and only a # list of token_ids are returned. return [t[0] for t in token_list] def _update_user_token_list(self, user_key, token_id, expires_isotime_str): current_time = self._get_current_time() revoked_token_list = set([t['id'] for t in self.list_revoked_tokens()]) with self._store.get_lock(user_key) as lock: filtered_list = [] token_list = self._get_user_token_list_with_expiry(user_key) for item in token_list: try: item_id, expires = self._format_token_index_item(item) except (ValueError, TypeError): # NOTE(morganfainberg): Skip on expected errors # possibilities from the `_format_token_index_item` method. continue if expires < current_time: LOG.debug(_('Token `%(token_id)s` is expired, removing ' 'from `%(user_key)s`.'), {'token_id': item_id, 'user_key': user_key}) continue if item_id in revoked_token_list: # NOTE(morganfainberg): If the token has been revoked, it # can safely be removed from this list. This helps to keep # the user_token_list as reasonably small as possible. LOG.debug(_('Token `%(token_id)s` is revoked, removing ' 'from `%(user_key)s`.'), {'token_id': item_id, 'user_key': user_key}) continue filtered_list.append(item) filtered_list.append((token_id, expires_isotime_str)) self._set_key(user_key, filtered_list, lock) return filtered_list def _get_current_time(self): return timeutils.normalize_time(timeutils.utcnow()) def _add_to_revocation_list(self, data, lock): filtered_list = [] revoked_token_data = {} current_time = self._get_current_time() expires = data['expires'] if isinstance(expires, six.string_types): expires = timeutils.parse_isotime(expires) expires = timeutils.normalize_time(expires) if expires < current_time: LOG.warning(_('Token `%s` is expired, not adding to the ' 'revocation list.'), data['id']) return revoked_token_data['expires'] = timeutils.isotime(expires, subsecond=True) revoked_token_data['id'] = data['id'] token_list = self._get_key_or_default(self.revocation_key, default=[]) if not isinstance(token_list, list): # NOTE(morganfainberg): In the case that the revocation list is not # in a format we understand, reinitialize it. This is an attempt to # not allow the revocation list to be completely broken if # somehow the key is changed outside of keystone (e.g. memcache # that is shared by multiple applications). Logging occurs at error # level so that the cloud administrators have some awareness that # the revocation_list needed to be cleared out. In all, this should # be recoverable. Keystone cannot control external applications # from changing a key in some backends, however, it is possible to # gracefully handle and notify of this event. LOG.error(_('Reinitializing revocation list due to error ' 'in loading revocation list from backend. ' 'Expected `list` type got `%(type)s`. Old ' 'revocation list data: %(list)r'), {'type': type(token_list), 'list': token_list}) token_list = [] # NOTE(morganfainberg): on revocation, cleanup the expired entries, try # to keep the list of tokens revoked at the minimum. for token_data in token_list: try: expires_at = timeutils.normalize_time( timeutils.parse_isotime(token_data['expires'])) except ValueError: LOG.warning(_('Removing `%s` from revocation list due to ' 'invalid expires data in revocation list.'), token_data.get('id', 'INVALID_TOKEN_DATA')) continue if expires_at > current_time: filtered_list.append(token_data) filtered_list.append(revoked_token_data) self._set_key(self.revocation_key, filtered_list, lock) def delete_token(self, token_id): # Test for existence with self._store.get_lock(self.revocation_key) as lock: data = self.get_token(token_id) ptk = self._prefix_token_id(token_id) result = self._delete_key(ptk) self._add_to_revocation_list(data, lock) return result def delete_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): return super(Token, self).delete_tokens( user_id=user_id, tenant_id=tenant_id, trust_id=trust_id, consumer_id=consumer_id, ) def _format_token_index_item(self, item): try: token_id, expires = item except (TypeError, ValueError): LOG.debug(_('Invalid token entry expected tuple of ' '`(, )` got: `%(item)r`'), dict(item=item)) raise try: expires = timeutils.normalize_time( timeutils.parse_isotime(expires)) except ValueError: LOG.debug(_('Invalid expires time on token `%(token_id)s`:' ' %(expires)r'), dict(token_id=token_id, expires=expires)) raise return token_id, expires def _token_match_tenant(self, token_ref, tenant_id): if token_ref.get('tenant'): return token_ref['tenant'].get('id') == tenant_id return False def _token_match_trust(self, token_ref, trust_id): if not token_ref.get('trust_id'): return False return token_ref['trust_id'] == trust_id def _token_match_consumer(self, token_ref, consumer_id): try: oauth = token_ref['token_data']['token']['OS-OAUTH1'] return oauth.get('consumer_id') == consumer_id except KeyError: return False def _list_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): # This function is used to generate the list of tokens that should be # revoked when revoking by token identifiers. This approach will be # deprecated soon, probably in the Juno release. Setting revoke_by_id # to False indicates that this kind of recording should not be # performed. In order to test the revocation events, tokens shouldn't # be deleted from the backends. This check ensures that tokens are # still recorded. if not CONF.token.revoke_by_id: return [] tokens = [] user_key = self._prefix_user_id(user_id) token_list = self._get_user_token_list_with_expiry(user_key) current_time = self._get_current_time() for item in token_list: try: token_id, expires = self._format_token_index_item(item) except (TypeError, ValueError): # NOTE(morganfainberg): Skip on expected error possibilities # from the `_format_token_index_item` method. continue if expires < current_time: continue try: token_ref = self.get_token(token_id) except exception.TokenNotFound: # NOTE(morganfainberg): Token doesn't exist, skip it. continue if token_ref: if tenant_id is not None: if not self._token_match_tenant(token_ref, tenant_id): continue if trust_id is not None: if not self._token_match_trust(token_ref, trust_id): continue if consumer_id is not None: if not self._token_match_consumer(token_ref, consumer_id): continue tokens.append(token_id) return tokens def list_revoked_tokens(self): revoked_token_list = self._get_key_or_default(self.revocation_key, default=[]) if isinstance(revoked_token_list, list): return revoked_token_list return [] def flush_expired_tokens(self): """Archive or delete tokens that have expired.""" raise exception.NotImplemented() keystone-2014.1/keystone/token/backends/__init__.py0000664000175400017540000000000012323716267023443 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/token/__init__.py0000664000175400017540000000135212323716272021700 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.token import controllers from keystone.token.core import * from keystone.token import provider from keystone.token import routers keystone-2014.1/keystone/token/provider.py0000664000175400017540000003336112323716267022004 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Token provider interface.""" import abc import six from keystone.common import cache from keystone.common import dependency from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils CONF = config.CONF LOG = log.getLogger(__name__) SHOULD_CACHE = cache.should_cache_fn('token') # NOTE(blk-u): The config options are not available at import time. EXPIRATION_TIME = lambda: CONF.token.cache_time # supported token versions V2 = 'v2.0' V3 = 'v3.0' VERSIONS = frozenset([V2, V3]) # default token providers PKI_PROVIDER = 'keystone.token.providers.pki.Provider' UUID_PROVIDER = 'keystone.token.providers.uuid.Provider' class UnsupportedTokenVersionException(Exception): """Token version is unrecognizable or unsupported.""" pass @dependency.requires('token_api') @dependency.optional('revoke_api') @dependency.provider('token_provider_api') class Manager(manager.Manager): """Default pivot point for the token provider backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ @classmethod def get_token_provider(cls): """Return package path to the configured token provider. The value should come from ``keystone.conf`` ``[token] provider``, however this method ensures backwards compatibility for ``keystone.conf`` ``[signing] token_format`` until Havana + 2. Return the provider based on ``token_format`` if ``provider`` is not set. Otherwise, ignore ``token_format`` and return the configured ``provider`` instead. """ if CONF.token.provider is not None: # NOTE(gyee): we are deprecating CONF.signing.token_format. This # code is to ensure the token provider configuration agrees with # CONF.signing.token_format. if (CONF.signing.token_format and ((CONF.token.provider == PKI_PROVIDER and CONF.signing.token_format != 'PKI') or (CONF.token.provider == UUID_PROVIDER and CONF.signing.token_format != 'UUID'))): raise exception.UnexpectedError( _('keystone.conf [signing] token_format (deprecated) ' 'conflicts with keystone.conf [token] provider')) return CONF.token.provider else: if not CONF.signing.token_format: # No token provider and no format, so use default (PKI) return PKI_PROVIDER msg = _('keystone.conf [signing] token_format is deprecated in ' 'favor of keystone.conf [token] provider') if CONF.signing.token_format == 'PKI': LOG.warning(msg) return PKI_PROVIDER elif CONF.signing.token_format == 'UUID': LOG.warning(msg) return UUID_PROVIDER else: raise exception.UnexpectedError( _('Unrecognized keystone.conf [signing] token_format: ' 'expected either \'UUID\' or \'PKI\'')) def __init__(self): super(Manager, self).__init__(self.get_token_provider()) def validate_token(self, token_id, belongs_to=None): unique_id = self.token_api.unique_id(token_id) # NOTE(morganfainberg): Ensure we never use the long-form token_id # (PKI) as part of the cache_key. token = self._validate_token(unique_id) self._token_belongs_to(token, belongs_to) self._is_valid_token(token) return token def check_revocation_v2(self, token): try: token_data = token['access'] except KeyError: raise exception.TokenNotFound(_('Failed to validate token')) if self.revoke_api is not None: token_values = self.revoke_api.model.build_token_values_v2( token_data, CONF.identity.default_domain_id) self.revoke_api.check_token(token_values) def validate_v2_token(self, token_id, belongs_to=None): unique_id = self.token_api.unique_id(token_id) # NOTE(morganfainberg): Ensure we never use the long-form token_id # (PKI) as part of the cache_key. token = self._validate_v2_token(unique_id) self.check_revocation_v2(token) self._token_belongs_to(token, belongs_to) self._is_valid_token(token) return token def check_revocation_v3(self, token): try: token_data = token['token'] except KeyError: raise exception.TokenNotFound(_('Failed to validate token')) if self.revoke_api is not None: token_values = self.revoke_api.model.build_token_values(token_data) self.revoke_api.check_token(token_values) def check_revocation(self, token): version = self.driver.get_token_version(token) if version == V2: return self.check_revocation_v2(token) else: return self.check_revocation_v3(token) def validate_v3_token(self, token_id): unique_id = self.token_api.unique_id(token_id) # NOTE(morganfainberg): Ensure we never use the long-form token_id # (PKI) as part of the cache_key. token = self._validate_v3_token(unique_id) self._is_valid_token(token) return token def check_v2_token(self, token_id, belongs_to=None): """Check the validity of the given V2 token. :param token_id: identity of the token :param belongs_to: optional identity of the scoped project :returns: None :raises: keystone.exception.Unauthorized """ # NOTE(morganfainberg): Ensure we never use the long-form token_id # (PKI) as part of the cache_key. unique_id = self.token_api.unique_id(token_id) self.validate_v2_token(unique_id, belongs_to=belongs_to) def check_v3_token(self, token_id): """Check the validity of the given V3 token. :param token_id: identity of the token :returns: None :raises: keystone.exception.Unauthorized """ # NOTE(morganfainberg): Ensure we never use the long-form token_id # (PKI) as part of the cache_key. unique_id = self.token_api.unique_id(token_id) self.validate_v3_token(unique_id) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def _validate_token(self, token_id): return self.driver.validate_token(token_id) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def _validate_v2_token(self, token_id): return self.driver.validate_v2_token(token_id) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def _validate_v3_token(self, token_id): return self.driver.validate_v3_token(token_id) def _is_valid_token(self, token): """Verify the token is valid format and has not expired.""" current_time = timeutils.normalize_time(timeutils.utcnow()) try: # Get the data we need from the correct location (V2 and V3 tokens # differ in structure, Try V3 first, fall back to V2 second) token_data = token.get('token', token.get('access')) expires_at = token_data.get('expires_at', token_data.get('expires')) if not expires_at: expires_at = token_data['token']['expires'] expiry = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) except Exception: LOG.exception(_('Unexpected error or malformed token determining ' 'token expiry: %s'), token) raise exception.TokenNotFound(_('Failed to validate token')) if current_time < expiry: self.check_revocation(token) # Token has not expired and has not been revoked. return None else: raise exception.TokenNotFound(_('Failed to validate token')) def _token_belongs_to(self, token, belongs_to): """Check if the token belongs to the right tenant. This is only used on v2 tokens. The structural validity of the token will have already been checked before this method is called. """ if belongs_to: token_data = token['access']['token'] if ('tenant' not in token_data or token_data['tenant']['id'] != belongs_to): raise exception.Unauthorized() def invalidate_individual_token_cache(self, token_id): # NOTE(morganfainberg): invalidate takes the exact same arguments as # the normal method, this means we need to pass "self" in (which gets # stripped off). # FIXME(morganfainberg): Does this cache actually need to be # invalidated? We maintain a cached revocation list, which should be # consulted before accepting a token as valid. For now we will # do the explicit individual token invalidation. self._validate_token.invalidate(self, token_id) self._validate_v2_token.invalidate(self, token_id) self._validate_v3_token.invalidate(self, token_id) @six.add_metaclass(abc.ABCMeta) class Provider(object): """Interface description for a Token provider.""" @abc.abstractmethod def get_token_version(self, token_data): """Return the version of the given token data. If the given token data is unrecognizable, UnsupportedTokenVersionException is raised. :param token_data: token_data :type token_data: dict :returns: token version string :raises: keystone.token.provider.UnsupportedTokenVersionException """ raise exception.NotImplemented() @abc.abstractmethod def issue_v2_token(self, token_ref, roles_ref=None, catalog_ref=None): """Issue a V2 token. :param token_ref: token data to generate token from :type token_ref: dict :param roles_ref: optional roles list :type roles_ref: dict :param catalog_ref: optional catalog information :type catalog_ref: dict :returns: (token_id, token_data) """ raise exception.NotImplemented() @abc.abstractmethod def issue_v3_token(self, user_id, method_names, expires_at=None, project_id=None, domain_id=None, auth_context=None, metadata_ref=None, include_catalog=True): """Issue a V3 Token. :param user_id: identity of the user :type user_id: string :param method_names: names of authentication methods :type method_names: list :param expires_at: optional time the token will expire :type expires_at: string :param project_id: optional project identity :type project_id: string :param domain_id: optional domain identity :type domain_id: string :param auth_context: optional context from the authorization plugins :type auth_context: dict :param metadata_ref: optional metadata reference :type metadata_ref: dict :param include_catalog: optional, include the catalog in token data :type include_catalog: boolean :returns: (token_id, token_data) """ raise exception.NotImplemented() @abc.abstractmethod def revoke_token(self, token_id): """Revoke a given token. :param token_id: identity of the token :type token_id: string :returns: None. """ raise exception.NotImplemented() @abc.abstractmethod def validate_token(self, token_id): """Detect token version and validate token and return the token data. Must raise Unauthorized exception if unable to validate token. :param token_id: identity of the token :type token_id: string :returns: token_data :raises: keystone.exception.TokenNotFound """ raise exception.NotImplemented() @abc.abstractmethod def validate_v2_token(self, token_id): """Validate the given V2 token and return the token data. Must raise Unauthorized exception if unable to validate token. :param token_id: identity of the token :type token_id: string :returns: token data :raises: keystone.exception.TokenNotFound """ raise exception.NotImplemented() @abc.abstractmethod def validate_v3_token(self, token_id): """Validate the given V3 token and return the token_data. :param token_id: identity of the token :type token_id: string :returns: token data :raises: keystone.exception.TokenNotFound """ raise exception.NotImplemented() @abc.abstractmethod def _get_token_id(self, token_data): """Generate the token_id based upon the data in token_data. :param token_data: token information :type token_data: dict returns: token identifier """ raise exception.NotImplemented() keystone-2014.1/keystone/middleware/0000775000175400017540000000000012323716511020557 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/middleware/ec2_token.py0000664000175400017540000000745612323716267023026 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """ Starting point for routing EC2 requests. """ from oslo.config import cfg import requests import webob.dec import webob.exc from keystone.common import config from keystone.common import wsgi from keystone.openstack.common import jsonutils keystone_ec2_opts = [ cfg.StrOpt('keystone_ec2_url', default='http://localhost:5000/v2.0/ec2tokens', help='URL to get token from ec2 request.'), cfg.StrOpt('keystone_ec2_keyfile', help='Required if EC2 server requires ' 'client certificate.'), cfg.StrOpt('keystone_ec2_certfile', help='Client certificate key ' 'filename. Required if EC2 server requires client ' 'certificate.'), cfg.StrOpt('keystone_ec2_cafile', help='A PEM encoded certificate ' 'authority to use when verifying HTTPS connections. Defaults ' 'to the system CAs.'), cfg.BoolOpt('keystone_ec2_insecure', default=False, help='Disable SSL ' 'certificate verification.'), ] CONF = config.CONF CONF.register_opts(keystone_ec2_opts) class EC2Token(wsgi.Middleware): """Authenticate an EC2 request with keystone and convert to token.""" @webob.dec.wsgify() def __call__(self, req): # Read request signature and access id. try: signature = req.params['Signature'] access = req.params['AWSAccessKeyId'] except KeyError: raise webob.exc.HTTPBadRequest() # Make a copy of args for authentication and signature verification. auth_params = dict(req.params) # Not part of authentication args auth_params.pop('Signature') # Authenticate the request. creds = { 'ec2Credentials': { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': auth_params, } } creds_json = jsonutils.dumps(creds) headers = {'Content-Type': 'application/json'} verify = True if CONF.keystone_ec2_insecure: verify = False elif CONF.keystone_ec2_cafile: verify = CONF.keystone_ec2_cafile cert = None if CONF.keystone_ec2_certfile and CONF.keystone_ec2_keyfile: cert = (CONF.keystone_ec2_certfile, CONF.keystone_ec2_keyfile) elif CONF.keystone_ec2_certfile: cert = CONF.keystone_ec2_certfile response = requests.post(CONF.keystone_ec2_url, data=creds_json, headers=headers, verify=verify, cert=cert) # NOTE(vish): We could save a call to keystone by # having keystone return token, tenant, # user, and roles from this call. result = response.json() try: token_id = result['access']['token']['id'] except (AttributeError, KeyError): raise webob.exc.HTTPBadRequest() # Authenticated! req.headers['X-Auth-Token'] = token_id return self.application keystone-2014.1/keystone/middleware/s3_token.py0000664000175400017540000000344712323716267022676 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011,2012 Akira YOSHIYAMA # All Rights Reserved. # # 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. # This source code is based ./auth_token.py and ./ec2_token.py. # See them for their copyright. """ S3 TOKEN MIDDLEWARE The S3 Token middleware is deprecated as of IceHouse. It's been moved into python-keystoneclient, `keystoneclient.middleware.s3_token`. This WSGI component: * Get a request from the swift3 middleware with an S3 Authorization access key. * Validate s3 token in Keystone. * Transform the account name to AUTH_%(tenant_name). """ from keystoneclient.middleware import s3_token from keystone.openstack.common import versionutils PROTOCOL_NAME = s3_token.PROTOCOL_NAME split_path = s3_token.split_path ServiceError = s3_token.ServiceError filter_factory = s3_token.filter_factory class S3Token(s3_token.S3Token): @versionutils.deprecated( versionutils.deprecated.ICEHOUSE, in_favor_of='keystoneclient.middleware.s3_token', remove_in=+1, what='keystone.middleware.s3_token') def __init__(self, app, conf): super(S3Token, self).__init__(app, conf) keystone-2014.1/keystone/middleware/core.py0000664000175400017540000002422712323716267022100 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import six import webob.dec from keystone.common import authorization from keystone.common import config from keystone.common import serializer from keystone.common import utils from keystone.common import wsgi from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils from keystone.openstack.common import log from keystone.openstack.common import versionutils CONF = config.CONF LOG = log.getLogger(__name__) # Header used to transmit the auth token AUTH_TOKEN_HEADER = 'X-Auth-Token' # Header used to transmit the subject token SUBJECT_TOKEN_HEADER = 'X-Subject-Token' # Environment variable used to pass the request context CONTEXT_ENV = wsgi.CONTEXT_ENV # Environment variable used to pass the request params PARAMS_ENV = wsgi.PARAMS_ENV class TokenAuthMiddleware(wsgi.Middleware): def process_request(self, request): token = request.headers.get(AUTH_TOKEN_HEADER) context = request.environ.get(CONTEXT_ENV, {}) context['token_id'] = token if SUBJECT_TOKEN_HEADER in request.headers: context['subject_token_id'] = ( request.headers.get(SUBJECT_TOKEN_HEADER)) request.environ[CONTEXT_ENV] = context class AdminTokenAuthMiddleware(wsgi.Middleware): """A trivial filter that checks for a pre-defined admin token. Sets 'is_admin' to true in the context, expected to be checked by methods that are admin-only. """ def process_request(self, request): token = request.headers.get(AUTH_TOKEN_HEADER) context = request.environ.get(CONTEXT_ENV, {}) context['is_admin'] = (token == CONF.admin_token) request.environ[CONTEXT_ENV] = context class PostParamsMiddleware(wsgi.Middleware): """Middleware to allow method arguments to be passed as POST parameters. Filters out the parameters `self`, `context` and anything beginning with an underscore. """ def process_request(self, request): params_parsed = request.params params = {} for k, v in six.iteritems(params_parsed): if k in ('self', 'context'): continue if k.startswith('_'): continue params[k] = v request.environ[PARAMS_ENV] = params class JsonBodyMiddleware(wsgi.Middleware): """Middleware to allow method arguments to be passed as serialized JSON. Accepting arguments as JSON is useful for accepting data that may be more complex than simple primitives. In this case we accept it as urlencoded data under the key 'json' as in json= but this could be extended to accept raw JSON in the POST body. Filters out the parameters `self`, `context` and anything beginning with an underscore. """ def process_request(self, request): # Abort early if we don't have any work to do params_json = request.body if not params_json: return # Reject unrecognized content types. Empty string indicates # the client did not explicitly set the header if request.content_type not in ('application/json', ''): e = exception.ValidationError(attribute='application/json', target='Content-Type header') return wsgi.render_exception(e, request=request) params_parsed = {} try: params_parsed = jsonutils.loads(params_json) except ValueError: e = exception.ValidationError(attribute='valid JSON', target='request body') return wsgi.render_exception(e, request=request) finally: if not params_parsed: params_parsed = {} params = {} for k, v in six.iteritems(params_parsed): if k in ('self', 'context'): continue if k.startswith('_'): continue params[k] = v request.environ[PARAMS_ENV] = params class XmlBodyMiddleware(wsgi.Middleware): """De/serializes XML to/from JSON.""" @versionutils.deprecated( what='keystone.middleware.core.XmlBodyMiddleware', as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='support for "application/json" only', remove_in=+2) def __init__(self, *args, **kwargs): super(XmlBodyMiddleware, self).__init__(*args, **kwargs) self.xmlns = None def process_request(self, request): """Transform the request from XML to JSON.""" incoming_xml = 'application/xml' in str(request.content_type) if incoming_xml and request.body: request.content_type = 'application/json' try: request.body = jsonutils.dumps( serializer.from_xml(request.body)) except Exception: LOG.exception('Serializer failed') e = exception.ValidationError(attribute='valid XML', target='request body') return wsgi.render_exception(e, request=request) def process_response(self, request, response): """Transform the response from JSON to XML.""" outgoing_xml = 'application/xml' in str(request.accept) if outgoing_xml and response.body: response.content_type = 'application/xml' try: body_obj = jsonutils.loads(response.body) response.body = serializer.to_xml(body_obj, xmlns=self.xmlns) except Exception: LOG.exception('Serializer failed') raise exception.Error(message=response.body) return response class XmlBodyMiddlewareV2(XmlBodyMiddleware): """De/serializes XML to/from JSON for v2.0 API.""" def __init__(self, *args, **kwargs): super(XmlBodyMiddlewareV2, self).__init__(*args, **kwargs) self.xmlns = 'http://docs.openstack.org/identity/api/v2.0' class XmlBodyMiddlewareV3(XmlBodyMiddleware): """De/serializes XML to/from JSON for v3 API.""" def __init__(self, *args, **kwargs): super(XmlBodyMiddlewareV3, self).__init__(*args, **kwargs) self.xmlns = 'http://docs.openstack.org/identity/api/v3' class NormalizingFilter(wsgi.Middleware): """Middleware filter to handle URL normalization.""" def process_request(self, request): """Normalizes URLs.""" # Removes a trailing slash from the given path, if any. if (len(request.environ['PATH_INFO']) > 1 and request.environ['PATH_INFO'][-1] == '/'): request.environ['PATH_INFO'] = request.environ['PATH_INFO'][:-1] # Rewrites path to root if no path is given. elif not request.environ['PATH_INFO']: request.environ['PATH_INFO'] = '/' class RequestBodySizeLimiter(wsgi.Middleware): """Limit the size of an incoming request.""" def __init__(self, *args, **kwargs): super(RequestBodySizeLimiter, self).__init__(*args, **kwargs) @webob.dec.wsgify() def __call__(self, req): if req.content_length > CONF.max_request_body_size: raise exception.RequestTooLarge() if req.content_length is None and req.is_body_readable: limiter = utils.LimitingReader(req.body_file, CONF.max_request_body_size) req.body_file = limiter return self.application class AuthContextMiddleware(wsgi.Middleware): """Build the authentication context from the request auth token.""" def _build_auth_context(self, request): token_id = request.headers.get(AUTH_TOKEN_HEADER) if token_id == CONF.admin_token: # NOTE(gyee): no need to proceed any further as the special admin # token is being handled by AdminTokenAuthMiddleware. This code # will not be impacted even if AdminTokenAuthMiddleware is removed # from the pipeline as "is_admin" is default to "False". This code # is independent of AdminTokenAuthMiddleware. return {} context = {'token_id': token_id} context['environment'] = request.environ try: token_ref = self.token_api.get_token(token_id) # TODO(ayoung): These two functions return the token in different # formats instead of two calls, only make one. However, the call # to get_token hits the caching layer, and does not validate the # token. In the future, this should be reduced to one call. if not CONF.token.revoke_by_id: self.token_api.token_provider_api.validate_token( context['token_id']) # TODO(gyee): validate_token_bind should really be its own # middleware wsgi.validate_token_bind(context, token_ref) return authorization.token_to_auth_context( token_ref['token_data']) except exception.TokenNotFound: LOG.warning(_('RBAC: Invalid token')) raise exception.Unauthorized() def process_request(self, request): if AUTH_TOKEN_HEADER not in request.headers: LOG.debug(_('Auth token not in the request header. ' 'Will not build auth context.')) return if authorization.AUTH_CONTEXT_ENV in request.environ: msg = _('Auth context already exists in the request environment') LOG.warning(msg) return auth_context = self._build_auth_context(request) LOG.debug(_('RBAC: auth_context: %s'), auth_context) request.environ[authorization.AUTH_CONTEXT_ENV] = auth_context keystone-2014.1/keystone/middleware/__init__.py0000664000175400017540000000120112323716272022666 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.middleware.core import * keystone-2014.1/keystone/controllers.py0000664000175400017540000001217612323716272021375 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import extension from keystone.common import wsgi from keystone import config from keystone import exception from keystone.openstack.common import log LOG = log.getLogger(__name__) CONF = config.CONF MEDIA_TYPE_JSON = 'application/vnd.openstack.identity-%s+json' MEDIA_TYPE_XML = 'application/vnd.openstack.identity-%s+xml' _VERSIONS = [] class Extensions(wsgi.Application): """Base extensions controller to be extended by public and admin API's.""" #extend in subclass to specify the set of extensions @property def extensions(self): return None def get_extensions_info(self, context): return {'extensions': {'values': self.extensions.values()}} def get_extension_info(self, context, extension_alias): try: return {'extension': self.extensions[extension_alias]} except KeyError: raise exception.NotFound(target=extension_alias) class AdminExtensions(Extensions): @property def extensions(self): return extension.ADMIN_EXTENSIONS class PublicExtensions(Extensions): @property def extensions(self): return extension.PUBLIC_EXTENSIONS def register_version(version): _VERSIONS.append(version) class Version(wsgi.Application): def __init__(self, version_type): self.endpoint_url_type = version_type super(Version, self).__init__() def _get_identity_url(self, context, version): """Returns a URL to keystone's own endpoint.""" url = self.base_url(context, self.endpoint_url_type) return '%s/%s/' % (url, version) def _get_versions_list(self, context): """The list of versions is dependent on the context.""" versions = {} if 'v2.0' in _VERSIONS: versions['v2.0'] = { 'id': 'v2.0', 'status': 'stable', 'updated': '2014-04-17T00:00:00Z', 'links': [ { 'rel': 'self', 'href': self._get_identity_url(context, 'v2.0'), }, { 'rel': 'describedby', 'type': 'text/html', 'href': 'http://docs.openstack.org/api/openstack-' 'identity-service/2.0/content/' }, { 'rel': 'describedby', 'type': 'application/pdf', 'href': 'http://docs.openstack.org/api/openstack-' 'identity-service/2.0/identity-dev-guide-' '2.0.pdf' } ], 'media-types': [ { 'base': 'application/json', 'type': MEDIA_TYPE_JSON % 'v2.0' }, { 'base': 'application/xml', 'type': MEDIA_TYPE_XML % 'v2.0' } ] } if 'v3' in _VERSIONS: versions['v3'] = { 'id': 'v3.0', 'status': 'stable', 'updated': '2013-03-06T00:00:00Z', 'links': [ { 'rel': 'self', 'href': self._get_identity_url(context, 'v3'), } ], 'media-types': [ { 'base': 'application/json', 'type': MEDIA_TYPE_JSON % 'v3' }, { 'base': 'application/xml', 'type': MEDIA_TYPE_XML % 'v3' } ] } return versions def get_versions(self, context): versions = self._get_versions_list(context) return wsgi.render_response(status=(300, 'Multiple Choices'), body={ 'versions': { 'values': versions.values() } }) def get_version_v2(self, context): versions = self._get_versions_list(context) if 'v2.0' in _VERSIONS: return wsgi.render_response(body={ 'version': versions['v2.0'] }) else: raise exception.VersionNotFound(version='v2.0') def get_version_v3(self, context): versions = self._get_versions_list(context) if 'v3' in _VERSIONS: return wsgi.render_response(body={ 'version': versions['v3'] }) else: raise exception.VersionNotFound(version='v3') keystone-2014.1/keystone/tests/0000775000175400017540000000000012323716511017604 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/test_versions.py0000664000175400017540000004356512323716272023106 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import random from keystone import config from keystone import controllers from keystone.openstack.common.fixture import moxstubout from keystone.openstack.common import jsonutils from keystone import tests from keystone.tests import matchers CONF = config.CONF v2_MEDIA_TYPES = [ { "base": "application/json", "type": "application/" "vnd.openstack.identity-v2.0+json" }, { "base": "application/xml", "type": "application/" "vnd.openstack.identity-v2.0+xml" } ] v2_HTML_DESCRIPTION = { "rel": "describedby", "type": "text/html", "href": "http://docs.openstack.org/api/" "openstack-identity-service/2.0/" "content/" } v2_PDF_DESCRIPTION = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.openstack.org/api/" "openstack-identity-service/2.0/" "identity-dev-guide-2.0.pdf" } v2_EXPECTED_RESPONSE = { "id": "v2.0", "status": "stable", "updated": "2014-04-17T00:00:00Z", "links": [ { "rel": "self", "href": "", # Will get filled in after initialization }, v2_HTML_DESCRIPTION, v2_PDF_DESCRIPTION ], "media-types": v2_MEDIA_TYPES } v2_VERSION_RESPONSE = { "version": v2_EXPECTED_RESPONSE } v3_MEDIA_TYPES = [ { "base": "application/json", "type": "application/" "vnd.openstack.identity-v3+json" }, { "base": "application/xml", "type": "application/" "vnd.openstack.identity-v3+xml" } ] v3_EXPECTED_RESPONSE = { "id": "v3.0", "status": "stable", "updated": "2013-03-06T00:00:00Z", "links": [ { "rel": "self", "href": "", # Will get filled in after initialization } ], "media-types": v3_MEDIA_TYPES } v3_VERSION_RESPONSE = { "version": v3_EXPECTED_RESPONSE } VERSIONS_RESPONSE = { "versions": { "values": [ v3_EXPECTED_RESPONSE, v2_EXPECTED_RESPONSE ] } } class VersionTestCase(tests.TestCase): def setUp(self): super(VersionTestCase, self).setUp() self.load_backends() self.public_app = self.loadapp('keystone', 'main') self.admin_app = self.loadapp('keystone', 'admin') self.config_fixture.config( public_endpoint='http://localhost:%(public_port)d', admin_endpoint='http://localhost:%(admin_port)d') fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs def config_overrides(self): super(VersionTestCase, self).config_overrides() port = random.randint(10000, 30000) self.config_fixture.config(public_port=port, admin_port=port) def _paste_in_port(self, response, port): for link in response['links']: if link['rel'] == 'self': link['href'] = port def test_public_versions(self): client = self.client(self.public_app) resp = client.get('/') self.assertEqual(resp.status_int, 300) data = jsonutils.loads(resp.body) expected = VERSIONS_RESPONSE for version in expected['versions']['values']: if version['id'] == 'v3.0': self._paste_in_port( version, 'http://localhost:%s/v3/' % CONF.public_port) elif version['id'] == 'v2.0': self._paste_in_port( version, 'http://localhost:%s/v2.0/' % CONF.public_port) self.assertEqual(data, expected) def test_admin_versions(self): client = self.client(self.admin_app) resp = client.get('/') self.assertEqual(resp.status_int, 300) data = jsonutils.loads(resp.body) expected = VERSIONS_RESPONSE for version in expected['versions']['values']: if version['id'] == 'v3.0': self._paste_in_port( version, 'http://localhost:%s/v3/' % CONF.admin_port) elif version['id'] == 'v2.0': self._paste_in_port( version, 'http://localhost:%s/v2.0/' % CONF.admin_port) self.assertEqual(data, expected) def test_use_site_url_if_endpoint_unset(self): self.config_fixture.config(public_endpoint=None, admin_endpoint=None) for app in (self.public_app, self.admin_app): client = self.client(app) resp = client.get('/') self.assertEqual(resp.status_int, 300) data = jsonutils.loads(resp.body) expected = VERSIONS_RESPONSE for version in expected['versions']['values']: # localhost happens to be the site url for tests if version['id'] == 'v3.0': self._paste_in_port( version, 'http://localhost/v3/') elif version['id'] == 'v2.0': self._paste_in_port( version, 'http://localhost/v2.0/') self.assertEqual(data, expected) def test_public_version_v2(self): client = self.client(self.public_app) resp = client.get('/v2.0/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v2_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost:%s/v2.0/' % CONF.public_port) self.assertEqual(data, expected) def test_admin_version_v2(self): client = self.client(self.admin_app) resp = client.get('/v2.0/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v2_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost:%s/v2.0/' % CONF.admin_port) self.assertEqual(data, expected) def test_use_site_url_if_endpoint_unset_v2(self): self.config_fixture.config(public_endpoint=None, admin_endpoint=None) for app in (self.public_app, self.admin_app): client = self.client(app) resp = client.get('/v2.0/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v2_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost/v2.0/') self.assertEqual(data, expected) def test_public_version_v3(self): client = self.client(self.public_app) resp = client.get('/v3/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v3_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost:%s/v3/' % CONF.public_port) self.assertEqual(data, expected) def test_admin_version_v3(self): client = self.client(self.public_app) resp = client.get('/v3/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v3_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost:%s/v3/' % CONF.admin_port) self.assertEqual(data, expected) def test_use_site_url_if_endpoint_unset_v3(self): self.config_fixture.config(public_endpoint=None, admin_endpoint=None) for app in (self.public_app, self.admin_app): client = self.client(app) resp = client.get('/v3/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v3_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost/v3/') self.assertEqual(data, expected) def test_v2_disabled(self): self.stubs.Set(controllers, '_VERSIONS', ['v3']) client = self.client(self.public_app) # request to /v2.0 should fail resp = client.get('/v2.0/') self.assertEqual(resp.status_int, 404) # request to /v3 should pass resp = client.get('/v3/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v3_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost:%s/v3/' % CONF.public_port) self.assertEqual(data, expected) # only v3 information should be displayed by requests to / v3_only_response = { "versions": { "values": [ v3_EXPECTED_RESPONSE ] } } self._paste_in_port(v3_only_response['versions']['values'][0], 'http://localhost:%s/v3/' % CONF.public_port) resp = client.get('/') self.assertEqual(resp.status_int, 300) data = jsonutils.loads(resp.body) self.assertEqual(data, v3_only_response) def test_v3_disabled(self): self.stubs.Set(controllers, '_VERSIONS', ['v2.0']) client = self.client(self.public_app) # request to /v3 should fail resp = client.get('/v3/') self.assertEqual(resp.status_int, 404) # request to /v2.0 should pass resp = client.get('/v2.0/') self.assertEqual(resp.status_int, 200) data = jsonutils.loads(resp.body) expected = v2_VERSION_RESPONSE self._paste_in_port(expected['version'], 'http://localhost:%s/v2.0/' % CONF.public_port) self.assertEqual(data, expected) # only v2 information should be displayed by requests to / v2_only_response = { "versions": { "values": [ v2_EXPECTED_RESPONSE ] } } self._paste_in_port(v2_only_response['versions']['values'][0], 'http://localhost:%s/v2.0/' % CONF.public_port) resp = client.get('/') self.assertEqual(resp.status_int, 300) data = jsonutils.loads(resp.body) self.assertEqual(data, v2_only_response) class XmlVersionTestCase(tests.TestCase): REQUEST_HEADERS = {'Accept': 'application/xml'} DOC_INTRO = '' XML_NAMESPACE_ATTR = 'xmlns="http://docs.openstack.org/identity/api/v2.0"' XML_NAMESPACE_V3 = 'xmlns="http://docs.openstack.org/identity/api/v3"' v2_VERSION_DATA = """ """ v2_VERSION_RESPONSE = ((DOC_INTRO + v2_VERSION_DATA) % dict(v2_namespace=XML_NAMESPACE_ATTR)) v3_VERSION_DATA = """ """ v3_VERSION_RESPONSE = ((DOC_INTRO + v3_VERSION_DATA) % dict(v3_namespace=XML_NAMESPACE_V3)) VERSIONS_RESPONSE = ((DOC_INTRO + """ """ + v3_VERSION_DATA + v2_VERSION_DATA + """ """) % dict(namespace=XML_NAMESPACE_ATTR, v3_namespace='', v2_namespace='')) def setUp(self): super(XmlVersionTestCase, self).setUp() self.load_backends() self.public_app = self.loadapp('keystone', 'main') self.admin_app = self.loadapp('keystone', 'admin') self.config_fixture.config( public_endpoint='http://localhost:%(public_port)d', admin_endpoint='http://localhost:%(admin_port)d') fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs def config_overrides(self): super(XmlVersionTestCase, self).config_overrides() port = random.randint(10000, 30000) self.config_fixture.config(public_port=port, admin_port=port) def test_public_versions(self): client = self.client(self.public_app) resp = client.get('/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 300) data = resp.body expected = self.VERSIONS_RESPONSE % dict(port=CONF.public_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_admin_versions(self): client = self.client(self.admin_app) resp = client.get('/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 300) data = resp.body expected = self.VERSIONS_RESPONSE % dict(port=CONF.admin_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_use_site_url_if_endpoint_unset(self): client = self.client(self.public_app) resp = client.get('/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 300) data = resp.body expected = self.VERSIONS_RESPONSE % dict(port=CONF.public_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_public_version_v2(self): client = self.client(self.public_app) resp = client.get('/v2.0/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 200) data = resp.body expected = self.v2_VERSION_RESPONSE % dict(port=CONF.public_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_admin_version_v2(self): client = self.client(self.admin_app) resp = client.get('/v2.0/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 200) data = resp.body expected = self.v2_VERSION_RESPONSE % dict(port=CONF.admin_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_public_version_v3(self): client = self.client(self.public_app) resp = client.get('/v3/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 200) data = resp.body expected = self.v3_VERSION_RESPONSE % dict(port=CONF.public_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_admin_version_v3(self): client = self.client(self.public_app) resp = client.get('/v3/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 200) data = resp.body expected = self.v3_VERSION_RESPONSE % dict(port=CONF.admin_port) self.assertThat(data, matchers.XMLEquals(expected)) def test_v2_disabled(self): self.stubs.Set(controllers, '_VERSIONS', ['v3']) client = self.client(self.public_app) # request to /v3 should pass resp = client.get('/v3/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 200) data = resp.body expected = self.v3_VERSION_RESPONSE % dict(port=CONF.public_port) self.assertThat(data, matchers.XMLEquals(expected)) # only v3 information should be displayed by requests to / v3_only_response = ((self.DOC_INTRO + '' + self.v3_VERSION_DATA + '') % dict(namespace=self.XML_NAMESPACE_ATTR, v3_namespace='') % dict(port=CONF.public_port)) resp = client.get('/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 300) data = resp.body self.assertThat(data, matchers.XMLEquals(v3_only_response)) def test_v3_disabled(self): self.stubs.Set(controllers, '_VERSIONS', ['v2.0']) client = self.client(self.public_app) # request to /v2.0 should pass resp = client.get('/v2.0/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 200) data = resp.body expected = self.v2_VERSION_RESPONSE % dict(port=CONF.public_port) self.assertThat(data, matchers.XMLEquals(expected)) # only v2 information should be displayed by requests to / v2_only_response = ((self.DOC_INTRO + '' + self.v2_VERSION_DATA + '') % dict(namespace=self.XML_NAMESPACE_ATTR, v2_namespace='') % dict(port=CONF.public_port)) resp = client.get('/', headers=self.REQUEST_HEADERS) self.assertEqual(resp.status_int, 300) data = resp.body self.assertThat(data, matchers.XMLEquals(v2_only_response)) keystone-2014.1/keystone/tests/test_keystoneclient.py0000664000175400017540000013022712323716272024266 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import datetime import os import uuid import webob import mock from keystone import config from keystone.openstack.common import jsonutils from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import default_fixtures from keystone.tests.ksfixtures import appserver CONF = config.CONF DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id OPENSTACK_REPO = 'https://review.openstack.org/p/openstack' KEYSTONECLIENT_REPO = '%s/python-keystoneclient.git' % OPENSTACK_REPO class CompatTestCase(tests.NoModule, tests.TestCase): def setUp(self): super(CompatTestCase, self).setUp() # FIXME(morganfainberg): Since we are running tests through the # controllers and some internal api drivers are SQL-only, the correct # approach is to ensure we have the correct backing store. The # credential api makes some very SQL specific assumptions that should # be addressed allowing for non-SQL based testing to occur. self.load_backends() self.load_fixtures(default_fixtures) # TODO(termie): add an admin user to the fixtures and use that user # override the fixtures, for now self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_admin['id']) conf = self._paste_config('keystone') fixture = self.useFixture(appserver.AppServer(conf, appserver.MAIN)) self.public_server = fixture.server fixture = self.useFixture(appserver.AppServer(conf, appserver.ADMIN)) self.admin_server = fixture.server self.addCleanup(self.cleanup_instance('public_server', 'admin_server')) if isinstance(self.checkout_info, str): revdir = self.checkout_info else: revdir = tests.checkout_vendor(*self.checkout_info) self.add_path(revdir) self.clear_module('keystoneclient') def _public_url(self): public_port = self.public_server.socket_info['socket'][1] return "http://localhost:%s/v2.0" % public_port def _admin_url(self): admin_port = self.admin_server.socket_info['socket'][1] return "http://localhost:%s/v2.0" % admin_port def _client(self, admin=False, **kwargs): from keystoneclient.v2_0 import client as ks_client url = self._admin_url() if admin else self._public_url() kc = ks_client.Client(endpoint=url, auth_url=self._public_url(), **kwargs) kc.authenticate() # have to manually overwrite the management url after authentication kc.management_url = url return kc def get_client(self, user_ref=None, tenant_ref=None, admin=False): if user_ref is None: user_ref = self.user_foo if tenant_ref is None: for user in default_fixtures.USERS: if user['id'] == user_ref['id']: tenant_id = user['tenants'][0] else: tenant_id = tenant_ref['id'] return self._client(username=user_ref['name'], password=user_ref['password'], tenant_id=tenant_id, admin=admin) class KeystoneClientTests(object): """Tests for all versions of keystoneclient.""" def test_authenticate_tenant_name_and_tenants(self): client = self.get_client() tenants = client.tenants.list() self.assertEqual(tenants[0].id, self.tenant_bar['id']) def test_authenticate_tenant_id_and_tenants(self): client = self._client(username=self.user_foo['name'], password=self.user_foo['password'], tenant_id='bar') tenants = client.tenants.list() self.assertEqual(tenants[0].id, self.tenant_bar['id']) def test_authenticate_invalid_tenant_id(self): from keystoneclient import exceptions as client_exceptions self.assertRaises(client_exceptions.Unauthorized, self._client, username=self.user_foo['name'], password=self.user_foo['password'], tenant_id='baz') def test_authenticate_token_no_tenant(self): client = self.get_client() token = client.auth_token token_client = self._client(token=token) tenants = token_client.tenants.list() self.assertEqual(tenants[0].id, self.tenant_bar['id']) def test_authenticate_token_tenant_id(self): client = self.get_client() token = client.auth_token token_client = self._client(token=token, tenant_id='bar') tenants = token_client.tenants.list() self.assertEqual(tenants[0].id, self.tenant_bar['id']) def test_authenticate_token_invalid_tenant_id(self): from keystoneclient import exceptions as client_exceptions client = self.get_client() token = client.auth_token self.assertRaises(client_exceptions.Unauthorized, self._client, token=token, tenant_id=uuid.uuid4().hex) def test_authenticate_token_invalid_tenant_name(self): from keystoneclient import exceptions as client_exceptions client = self.get_client() token = client.auth_token self.assertRaises(client_exceptions.Unauthorized, self._client, token=token, tenant_name=uuid.uuid4().hex) def test_authenticate_token_tenant_name(self): client = self.get_client() token = client.auth_token token_client = self._client(token=token, tenant_name='BAR') tenants = token_client.tenants.list() self.assertEqual(tenants[0].id, self.tenant_bar['id']) self.assertEqual(tenants[0].id, self.tenant_bar['id']) def test_authenticate_and_delete_token(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) token = client.auth_token token_client = self._client(token=token) tenants = token_client.tenants.list() self.assertEqual(tenants[0].id, self.tenant_bar['id']) client.tokens.delete(token_client.auth_token) self.assertRaises(client_exceptions.Unauthorized, token_client.tenants.list) def test_authenticate_no_password(self): from keystoneclient import exceptions as client_exceptions user_ref = self.user_foo.copy() user_ref['password'] = None self.assertRaises(client_exceptions.AuthorizationFailure, self.get_client, user_ref) def test_authenticate_no_username(self): from keystoneclient import exceptions as client_exceptions user_ref = self.user_foo.copy() user_ref['name'] = None self.assertRaises(client_exceptions.AuthorizationFailure, self.get_client, user_ref) def test_authenticate_disabled_tenant(self): from keystoneclient import exceptions as client_exceptions admin_client = self.get_client(admin=True) tenant = { 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, 'enabled': False, } tenant_ref = admin_client.tenants.create( tenant_name=tenant['name'], description=tenant['description'], enabled=tenant['enabled']) tenant['id'] = tenant_ref.id user = { 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'email': uuid.uuid4().hex, 'tenant_id': tenant['id'], } user_ref = admin_client.users.create( name=user['name'], password=user['password'], email=user['email'], tenant_id=user['tenant_id']) user['id'] = user_ref.id # password authentication self.assertRaises( client_exceptions.Unauthorized, self._client, username=user['name'], password=user['password'], tenant_id=tenant['id']) # token authentication client = self._client( username=user['name'], password=user['password']) self.assertRaises( client_exceptions.Unauthorized, self._client, token=client.auth_token, tenant_id=tenant['id']) # FIXME(ja): this test should require the "keystone:admin" roled # (probably the role set via --keystone_admin_role flag) # FIXME(ja): add a test that admin endpoint is only sent to admin user # FIXME(ja): add a test that admin endpoint returns unauthorized if not # admin def test_tenant_create_update_and_delete(self): from keystoneclient import exceptions as client_exceptions tenant_name = 'original_tenant' tenant_description = 'My original tenant!' tenant_enabled = True client = self.get_client(admin=True) # create, get, and list a tenant tenant = client.tenants.create(tenant_name=tenant_name, description=tenant_description, enabled=tenant_enabled) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertEqual(tenant.enabled, tenant_enabled) tenant = client.tenants.get(tenant_id=tenant.id) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertEqual(tenant.enabled, tenant_enabled) tenant = [t for t in client.tenants.list() if t.id == tenant.id].pop() self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertEqual(tenant.enabled, tenant_enabled) # update, get, and list a tenant tenant_name = 'updated_tenant' tenant_description = 'Updated tenant!' tenant_enabled = False tenant = client.tenants.update(tenant_id=tenant.id, tenant_name=tenant_name, enabled=tenant_enabled, description=tenant_description) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertEqual(tenant.enabled, tenant_enabled) tenant = client.tenants.get(tenant_id=tenant.id) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertEqual(tenant.enabled, tenant_enabled) tenant = [t for t in client.tenants.list() if t.id == tenant.id].pop() self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertEqual(tenant.enabled, tenant_enabled) # delete, get, and list a tenant client.tenants.delete(tenant=tenant.id) self.assertRaises(client_exceptions.NotFound, client.tenants.get, tenant.id) self.assertFalse([t for t in client.tenants.list() if t.id == tenant.id]) def test_tenant_create_update_and_delete_unicode(self): from keystoneclient import exceptions as client_exceptions tenant_name = u'original \u540d\u5b57' tenant_description = 'My original tenant!' tenant_enabled = True client = self.get_client(admin=True) # create, get, and list a tenant tenant = client.tenants.create(tenant_name, description=tenant_description, enabled=tenant_enabled) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertIs(tenant.enabled, tenant_enabled) tenant = client.tenants.get(tenant.id) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertIs(tenant.enabled, tenant_enabled) # multiple tenants exist due to fixtures, so find the one we're testing tenant = [t for t in client.tenants.list() if t.id == tenant.id].pop() self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertIs(tenant.enabled, tenant_enabled) # update, get, and list a tenant tenant_name = u'updated \u540d\u5b57' tenant_description = 'Updated tenant!' tenant_enabled = False tenant = client.tenants.update(tenant.id, tenant_name=tenant_name, enabled=tenant_enabled, description=tenant_description) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertIs(tenant.enabled, tenant_enabled) tenant = client.tenants.get(tenant.id) self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertIs(tenant.enabled, tenant_enabled) tenant = [t for t in client.tenants.list() if t.id == tenant.id].pop() self.assertEqual(tenant.name, tenant_name) self.assertEqual(tenant.description, tenant_description) self.assertIs(tenant.enabled, tenant_enabled) # delete, get, and list a tenant client.tenants.delete(tenant.id) self.assertRaises(client_exceptions.NotFound, client.tenants.get, tenant.id) self.assertFalse([t for t in client.tenants.list() if t.id == tenant.id]) def test_tenant_create_no_name(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.BadRequest, client.tenants.create, tenant_name="") def test_tenant_delete_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.tenants.delete, tenant=uuid.uuid4().hex) def test_tenant_get_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.tenants.get, tenant_id=uuid.uuid4().hex) def test_tenant_update_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.tenants.update, tenant_id=uuid.uuid4().hex) def test_tenant_list(self): client = self.get_client() tenants = client.tenants.list() self.assertEqual(len(tenants), 1) # Admin endpoint should return *all* tenants client = self.get_client(admin=True) tenants = client.tenants.list() self.assertEqual(len(tenants), len(default_fixtures.TENANTS)) def test_invalid_password(self): from keystoneclient import exceptions as client_exceptions good_client = self._client(username=self.user_foo['name'], password=self.user_foo['password']) good_client.tenants.list() self.assertRaises(client_exceptions.Unauthorized, self._client, username=self.user_foo['name'], password=uuid.uuid4().hex) def test_invalid_user_and_password(self): from keystoneclient import exceptions as client_exceptions self.assertRaises(client_exceptions.Unauthorized, self._client, username=uuid.uuid4().hex, password=uuid.uuid4().hex) def test_change_password_invalidates_token(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) username = uuid.uuid4().hex passwd = uuid.uuid4().hex user = client.users.create(name=username, password=passwd, email=uuid.uuid4().hex) token_id = client.tokens.authenticate(username=username, password=passwd).id # authenticate with a token should work before a password change client.tokens.authenticate(token=token_id) client.users.update_password(user=user.id, password=uuid.uuid4().hex) # authenticate with a token should not work after a password change self.assertRaises(client_exceptions.Unauthorized, client.tokens.authenticate, token=token_id) def test_disable_tenant_invalidates_token(self): from keystoneclient import exceptions as client_exceptions admin_client = self.get_client(admin=True) foo_client = self.get_client(self.user_foo) tenant_bar = admin_client.tenants.get(self.tenant_bar['id']) # Disable the tenant. tenant_bar.update(enabled=False) # Test that the token has been removed. self.assertRaises(client_exceptions.Unauthorized, foo_client.tokens.authenticate, token=foo_client.auth_token) # Test that the user access has been disabled. self.assertRaises(client_exceptions.Unauthorized, self.get_client, self.user_foo) def test_delete_tenant_invalidates_token(self): from keystoneclient import exceptions as client_exceptions admin_client = self.get_client(admin=True) foo_client = self.get_client(self.user_foo) tenant_bar = admin_client.tenants.get(self.tenant_bar['id']) # Delete the tenant. tenant_bar.delete() # Test that the token has been removed. self.assertRaises(client_exceptions.Unauthorized, foo_client.tokens.authenticate, token=foo_client.auth_token) # Test that the user access has been disabled. self.assertRaises(client_exceptions.Unauthorized, self.get_client, self.user_foo) def test_disable_user_invalidates_token(self): from keystoneclient import exceptions as client_exceptions admin_client = self.get_client(admin=True) foo_client = self.get_client(self.user_foo) admin_client.users.update_enabled(user=self.user_foo['id'], enabled=False) self.assertRaises(client_exceptions.Unauthorized, foo_client.tokens.authenticate, token=foo_client.auth_token) self.assertRaises(client_exceptions.Unauthorized, self.get_client, self.user_foo) def test_delete_user_invalidates_token(self): from keystoneclient import exceptions as client_exceptions admin_client = self.get_client(admin=True) client = self.get_client(admin=False) username = uuid.uuid4().hex password = uuid.uuid4().hex user_id = admin_client.users.create( name=username, password=password, email=uuid.uuid4().hex).id token_id = client.tokens.authenticate( username=username, password=password).id # token should be usable before the user is deleted client.tokens.authenticate(token=token_id) admin_client.users.delete(user=user_id) # authenticate with a token should not work after the user is deleted self.assertRaises(client_exceptions.Unauthorized, client.tokens.authenticate, token=token_id) @mock.patch.object(timeutils, 'utcnow') def test_token_expiry_maintained(self, mock_utcnow): now = datetime.datetime.utcnow() mock_utcnow.return_value = now foo_client = self.get_client(self.user_foo) orig_token = foo_client.service_catalog.catalog['token'] mock_utcnow.return_value = now + datetime.timedelta(seconds=1) reauthenticated_token = foo_client.tokens.authenticate( token=foo_client.auth_token) self.assertCloseEnoughForGovernmentWork( timeutils.parse_isotime(orig_token['expires']), timeutils.parse_isotime(reauthenticated_token.expires)) def test_user_create_update_delete(self): from keystoneclient import exceptions as client_exceptions test_username = 'new_user' client = self.get_client(admin=True) user = client.users.create(name=test_username, password='password', email='user1@test.com') self.assertEqual(user.name, test_username) user = client.users.get(user=user.id) self.assertEqual(user.name, test_username) user = client.users.update(user=user, name=test_username, email='user2@test.com') self.assertEqual(user.email, 'user2@test.com') # NOTE(termie): update_enabled doesn't return anything, probably a bug client.users.update_enabled(user=user, enabled=False) user = client.users.get(user.id) self.assertFalse(user.enabled) self.assertRaises(client_exceptions.Unauthorized, self._client, username=test_username, password='password') client.users.update_enabled(user, True) user = client.users.update_password(user=user, password='password2') self._client(username=test_username, password='password2') user = client.users.update_tenant(user=user, tenant='bar') # TODO(ja): once keystonelight supports default tenant # when you login without specifying tenant, the # token should be scoped to tenant 'bar' client.users.delete(user.id) self.assertRaises(client_exceptions.NotFound, client.users.get, user.id) # Test creating a user with a tenant (auto-add to tenant) user2 = client.users.create(name=test_username, password='password', email='user1@test.com', tenant_id='bar') self.assertEqual(user2.name, test_username) def test_update_default_tenant_to_existing_value(self): client = self.get_client(admin=True) user = client.users.create( name=uuid.uuid4().hex, password=uuid.uuid4().hex, email=uuid.uuid4().hex, tenant_id=self.tenant_bar['id']) # attempting to update the tenant with the existing value should work user = client.users.update_tenant( user=user, tenant=self.tenant_bar['id']) def test_user_create_no_string_password(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.BadRequest, client.users.create, name='test_user', password=12345, email=uuid.uuid4().hex) def test_user_create_no_name(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.BadRequest, client.users.create, name="", password=uuid.uuid4().hex, email=uuid.uuid4().hex) def test_user_create_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.users.create, name=uuid.uuid4().hex, password=uuid.uuid4().hex, email=uuid.uuid4().hex, tenant_id=uuid.uuid4().hex) def test_user_get_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.users.get, user=uuid.uuid4().hex) def test_user_list_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.users.list, tenant_id=uuid.uuid4().hex) def test_user_update_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.users.update, user=uuid.uuid4().hex) def test_user_update_tenant(self): client = self.get_client(admin=True) tenant_id = uuid.uuid4().hex user = client.users.update(user=self.user_foo['id'], tenant_id=tenant_id) self.assertEqual(tenant_id, user.tenant_id) def test_user_update_password_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.users.update_password, user=uuid.uuid4().hex, password=uuid.uuid4().hex) def test_user_delete_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.users.delete, user=uuid.uuid4().hex) def test_user_list(self): client = self.get_client(admin=True) users = client.users.list() self.assertTrue(len(users) > 0) user = users[0] self.assertRaises(AttributeError, lambda: user.password) def test_user_get(self): client = self.get_client(admin=True) user = client.users.get(user=self.user_foo['id']) self.assertRaises(AttributeError, lambda: user.password) def test_role_get(self): client = self.get_client(admin=True) role = client.roles.get(role=self.role_admin['id']) self.assertEqual(role.id, self.role_admin['id']) def test_role_crud(self): from keystoneclient import exceptions as client_exceptions test_role = 'new_role' client = self.get_client(admin=True) role = client.roles.create(name=test_role) self.assertEqual(role.name, test_role) role = client.roles.get(role=role.id) self.assertEqual(role.name, test_role) client.roles.delete(role=role.id) self.assertRaises(client_exceptions.NotFound, client.roles.delete, role=role.id) self.assertRaises(client_exceptions.NotFound, client.roles.get, role=role.id) def test_role_create_no_name(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.BadRequest, client.roles.create, name="") def test_role_get_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.roles.get, role=uuid.uuid4().hex) def test_role_delete_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.roles.delete, role=uuid.uuid4().hex) def test_role_list_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.roles.roles_for_user, user=uuid.uuid4().hex, tenant=uuid.uuid4().hex) self.assertRaises(client_exceptions.NotFound, client.roles.roles_for_user, user=self.user_foo['id'], tenant=uuid.uuid4().hex) self.assertRaises(client_exceptions.NotFound, client.roles.roles_for_user, user=uuid.uuid4().hex, tenant=self.tenant_bar['id']) def test_role_list(self): client = self.get_client(admin=True) roles = client.roles.list() # TODO(devcamcar): This assert should be more specific. self.assertTrue(len(roles) > 0) def test_service_crud(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) service_name = uuid.uuid4().hex service_type = uuid.uuid4().hex service_desc = uuid.uuid4().hex # create & read service = client.services.create(name=service_name, service_type=service_type, description=service_desc) self.assertEqual(service_name, service.name) self.assertEqual(service_type, service.type) self.assertEqual(service_desc, service.description) service = client.services.get(id=service.id) self.assertEqual(service_name, service.name) self.assertEqual(service_type, service.type) self.assertEqual(service_desc, service.description) service = [x for x in client.services.list() if x.id == service.id][0] self.assertEqual(service_name, service.name) self.assertEqual(service_type, service.type) self.assertEqual(service_desc, service.description) # update is not supported in API v2... # delete & read client.services.delete(id=service.id) self.assertRaises(client_exceptions.NotFound, client.services.get, id=service.id) services = [x for x in client.services.list() if x.id == service.id] self.assertEqual(len(services), 0) def test_service_delete_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.services.delete, id=uuid.uuid4().hex) def test_service_get_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.services.get, id=uuid.uuid4().hex) def test_endpoint_delete_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.endpoints.delete, id=uuid.uuid4().hex) def test_admin_requires_adminness(self): from keystoneclient import exceptions as client_exceptions # FIXME(ja): this should be Unauthorized exception = client_exceptions.ClientException two = self.get_client(self.user_two, admin=True) # non-admin user # USER CRUD self.assertRaises(exception, two.users.list) self.assertRaises(exception, two.users.get, user=self.user_two['id']) self.assertRaises(exception, two.users.create, name='oops', password='password', email='oops@test.com') self.assertRaises(exception, two.users.delete, user=self.user_foo['id']) # TENANT CRUD self.assertRaises(exception, two.tenants.list) self.assertRaises(exception, two.tenants.get, tenant_id=self.tenant_bar['id']) self.assertRaises(exception, two.tenants.create, tenant_name='oops', description="shouldn't work!", enabled=True) self.assertRaises(exception, two.tenants.delete, tenant=self.tenant_baz['id']) # ROLE CRUD self.assertRaises(exception, two.roles.get, role=self.role_admin['id']) self.assertRaises(exception, two.roles.list) self.assertRaises(exception, two.roles.create, name='oops') self.assertRaises(exception, two.roles.delete, role=self.role_admin['id']) # TODO(ja): MEMBERSHIP CRUD # TODO(ja): determine what else todo def test_tenant_add_and_remove_user(self): client = self.get_client(admin=True) client.roles.add_user_role(tenant=self.tenant_bar['id'], user=self.user_two['id'], role=self.role_other['id']) user_refs = client.tenants.list_users(tenant=self.tenant_bar['id']) self.assertTrue(self.user_two['id'] in [x.id for x in user_refs]) client.roles.remove_user_role(tenant=self.tenant_bar['id'], user=self.user_two['id'], role=self.role_other['id']) roles = client.roles.roles_for_user(user=self.user_foo['id'], tenant=self.tenant_bar['id']) self.assertNotIn(self.role_other['id'], roles) user_refs = client.tenants.list_users(tenant=self.tenant_bar['id']) self.assertNotIn(self.user_two['id'], [x.id for x in user_refs]) def test_user_role_add_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.roles.add_user_role, tenant=uuid.uuid4().hex, user=self.user_foo['id'], role=self.role_member['id']) self.assertRaises(client_exceptions.NotFound, client.roles.add_user_role, tenant=self.tenant_baz['id'], user=self.user_foo['id'], role=uuid.uuid4().hex) def test_user_role_add_no_user(self): # If add_user_role and user doesn't exist, doesn't fail. client = self.get_client(admin=True) client.roles.add_user_role(tenant=self.tenant_baz['id'], user=uuid.uuid4().hex, role=self.role_member['id']) def test_user_role_remove_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.roles.remove_user_role, tenant=uuid.uuid4().hex, user=self.user_foo['id'], role=self.role_member['id']) self.assertRaises(client_exceptions.NotFound, client.roles.remove_user_role, tenant=self.tenant_baz['id'], user=uuid.uuid4().hex, role=self.role_member['id']) self.assertRaises(client_exceptions.NotFound, client.roles.remove_user_role, tenant=self.tenant_baz['id'], user=self.user_foo['id'], role=uuid.uuid4().hex) self.assertRaises(client_exceptions.NotFound, client.roles.remove_user_role, tenant=self.tenant_baz['id'], user=self.user_foo['id'], role=self.role_member['id']) def test_tenant_list_marker(self): client = self.get_client() # Add two arbitrary tenants to user for testing purposes for i in range(2): tenant_id = uuid.uuid4().hex tenant = {'name': 'tenant-%s' % tenant_id, 'id': tenant_id, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(tenant_id, tenant) self.assignment_api.add_user_to_project(tenant_id, self.user_foo['id']) tenants = client.tenants.list() self.assertEqual(len(tenants), 3) tenants_marker = client.tenants.list(marker=tenants[0].id) self.assertEqual(len(tenants_marker), 2) self.assertEqual(tenants[1].name, tenants_marker[0].name) self.assertEqual(tenants[2].name, tenants_marker[1].name) def test_tenant_list_marker_not_found(self): from keystoneclient import exceptions as client_exceptions client = self.get_client() self.assertRaises(client_exceptions.BadRequest, client.tenants.list, marker=uuid.uuid4().hex) def test_tenant_list_limit(self): client = self.get_client() # Add two arbitrary tenants to user for testing purposes for i in range(2): tenant_id = uuid.uuid4().hex tenant = {'name': 'tenant-%s' % tenant_id, 'id': tenant_id, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(tenant_id, tenant) self.assignment_api.add_user_to_project(tenant_id, self.user_foo['id']) tenants = client.tenants.list() self.assertEqual(len(tenants), 3) tenants_limited = client.tenants.list(limit=2) self.assertEqual(len(tenants_limited), 2) self.assertEqual(tenants[0].name, tenants_limited[0].name) self.assertEqual(tenants[1].name, tenants_limited[1].name) def test_tenant_list_limit_bad_value(self): from keystoneclient import exceptions as client_exceptions client = self.get_client() self.assertRaises(client_exceptions.BadRequest, client.tenants.list, limit='a') self.assertRaises(client_exceptions.BadRequest, client.tenants.list, limit=-1) def test_roles_get_by_user(self): client = self.get_client(admin=True) roles = client.roles.roles_for_user(user=self.user_foo['id'], tenant=self.tenant_bar['id']) self.assertTrue(len(roles) > 0) def test_user_can_update_passwd(self): client = self.get_client(self.user_two) token_id = client.auth_token new_password = uuid.uuid4().hex # TODO(derekh): Update to use keystoneclient when available class FakeResponse(object): def start_fake_response(self, status, headers): self.response_status = int(status.split(' ', 1)[0]) self.response_headers = dict(headers) responseobject = FakeResponse() req = webob.Request.blank( '/v2.0/OS-KSCRUD/users/%s' % self.user_two['id'], headers={'X-Auth-Token': token_id}) req.method = 'PATCH' req.body = ('{"user":{"password":"%s","original_password":"%s"}}' % (new_password, self.user_two['password'])) self.public_server.application(req.environ, responseobject.start_fake_response) self.user_two['password'] = new_password self.get_client(self.user_two) def test_user_cannot_update_other_users_passwd(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(self.user_two) token_id = client.auth_token new_password = uuid.uuid4().hex # TODO(derekh): Update to use keystoneclient when available class FakeResponse(object): def start_fake_response(self, status, headers): self.response_status = int(status.split(' ', 1)[0]) self.response_headers = dict(headers) responseobject = FakeResponse() req = webob.Request.blank( '/v2.0/OS-KSCRUD/users/%s' % self.user_foo['id'], headers={'X-Auth-Token': token_id}) req.method = 'PATCH' req.body = ('{"user":{"password":"%s","original_password":"%s"}}' % (new_password, self.user_two['password'])) self.public_server.application(req.environ, responseobject.start_fake_response) self.assertEqual(403, responseobject.response_status) self.user_two['password'] = new_password self.assertRaises(client_exceptions.Unauthorized, self.get_client, self.user_two) def test_tokens_after_user_update_passwd(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(self.user_two) token_id = client.auth_token new_password = uuid.uuid4().hex # TODO(derekh): Update to use keystoneclient when available class FakeResponse(object): def start_fake_response(self, status, headers): self.response_status = int(status.split(' ', 1)[0]) self.response_headers = dict(headers) responseobject = FakeResponse() req = webob.Request.blank( '/v2.0/OS-KSCRUD/users/%s' % self.user_two['id'], headers={'X-Auth-Token': token_id}) req.method = 'PATCH' req.body = ('{"user":{"password":"%s","original_password":"%s"}}' % (new_password, self.user_two['password'])) rv = self.public_server.application( req.environ, responseobject.start_fake_response) response_json = jsonutils.loads(rv.pop()) new_token_id = response_json['access']['token']['id'] self.assertRaises(client_exceptions.Unauthorized, client.tenants.list) client.auth_token = new_token_id client.tenants.list() class KcMasterTestCase(CompatTestCase, KeystoneClientTests): checkout_info = (KEYSTONECLIENT_REPO, 'master') class KcOptTestCase(KcMasterTestCase): # Set KSCTEST_PATH to the keystoneclient directory, then run this test. # # For example, to test your local keystoneclient, # # KSCTEST_PATH=/opt/stack/python-keystoneclient \ # tox -e py27 test_keystoneclient.KcOptTestCase def setUp(self): self.checkout_info = os.environ.get('KSCTEST_PATH') if not self.checkout_info: self.skip('Set KSCTEST_PATH env to test with local client') super(KcOptTestCase, self).setUp() keystone-2014.1/keystone/tests/test_cache.py0000664000175400017540000002333112323716267022272 0ustar jenkinsjenkins00000000000000# Copyright 2013 Metacloud # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy from dogpile.cache import api from dogpile.cache import proxy from keystone.common import cache from keystone import config from keystone import exception from keystone import tests CONF = config.CONF NO_VALUE = api.NO_VALUE def _copy_value(value): if value is not NO_VALUE: value = copy.deepcopy(value) return value # NOTE(morganfainberg): WARNING - It is not recommended to use the Memory # backend for dogpile.cache in a real deployment under any circumstances. The # backend does no cleanup of expired values and therefore will leak memory. The # backend is not implemented in a way to share data across processes (e.g. # Keystone in HTTPD. This proxy is a hack to get around the lack of isolation # of values in memory. Currently it blindly stores and retrieves the values # from the cache, and modifications to dicts/lists/etc returned can result in # changes to the cached values. In short, do not use the dogpile.cache.memory # backend unless you are running tests or expecting odd/strange results. class CacheIsolatingProxy(proxy.ProxyBackend): """Proxy that forces a memory copy of stored values. The default in-memory cache-region does not perform a copy on values it is meant to cache. Therefore if the value is modified after set or after get, the cached value also is modified. This proxy does a copy as the last thing before storing data. """ def get(self, key): return _copy_value(self.proxied.get(key)) def set(self, key, value): self.proxied.set(key, _copy_value(value)) class TestProxy(proxy.ProxyBackend): def get(self, key): value = _copy_value(self.proxied.get(key)) if value is not NO_VALUE: if isinstance(value[0], TestProxyValue): value[0].cached = True return value class TestProxyValue(object): def __init__(self, value): self.value = value self.cached = False class CacheRegionTest(tests.TestCase): def setUp(self): super(CacheRegionTest, self).setUp() self.region = cache.make_region() cache.configure_cache_region(self.region) self.region.wrap(TestProxy) self.test_value = TestProxyValue('Decorator Test') def _add_test_caching_option(self): self.config_fixture.register_opt( config.config.cfg.BoolOpt('caching', default=True), group='cache') def _get_cacheable_function(self): SHOULD_CACHE_FN = cache.should_cache_fn('cache') @self.region.cache_on_arguments(should_cache_fn=SHOULD_CACHE_FN) def cacheable_function(value): return value return cacheable_function def test_region_built_with_proxy_direct_cache_test(self): # Verify cache regions are properly built with proxies. test_value = TestProxyValue('Direct Cache Test') self.region.set('cache_test', test_value) cached_value = self.region.get('cache_test') self.assertTrue(cached_value.cached) def test_cache_region_no_error_multiple_config(self): # Verify configuring the CacheRegion again doesn't error. cache.configure_cache_region(self.region) cache.configure_cache_region(self.region) def test_should_cache_fn_global_cache_enabled(self): # Verify should_cache_fn generates a sane function for subsystem and # functions as expected with caching globally enabled. cacheable_function = self._get_cacheable_function() self.config_fixture.config(group='cache', enabled=True) cacheable_function(self.test_value) cached_value = cacheable_function(self.test_value) self.assertTrue(cached_value.cached) def test_should_cache_fn_global_cache_disabled(self): # Verify should_cache_fn generates a sane function for subsystem and # functions as expected with caching globally disabled. cacheable_function = self._get_cacheable_function() self.config_fixture.config(group='cache', enabled=False) cacheable_function(self.test_value) cached_value = cacheable_function(self.test_value) self.assertFalse(cached_value.cached) def test_should_cache_fn_global_cache_disabled_section_cache_enabled(self): # Verify should_cache_fn generates a sane function for subsystem and # functions as expected with caching globally disabled and the specific # section caching enabled. cacheable_function = self._get_cacheable_function() self._add_test_caching_option() self.config_fixture.config(group='cache', enabled=False) self.config_fixture.config(group='cache', caching=True) cacheable_function(self.test_value) cached_value = cacheable_function(self.test_value) self.assertFalse(cached_value.cached) def test_should_cache_fn_global_cache_enabled_section_cache_disabled(self): # Verify should_cache_fn generates a sane function for subsystem and # functions as expected with caching globally enabled and the specific # section caching disabled. cacheable_function = self._get_cacheable_function() self._add_test_caching_option() self.config_fixture.config(group='cache', enabled=True) self.config_fixture.config(group='cache', caching=False) cacheable_function(self.test_value) cached_value = cacheable_function(self.test_value) self.assertFalse(cached_value.cached) def test_should_cache_fn_global_cache_enabled_section_cache_enabled(self): # Verify should_cache_fn generates a sane function for subsystem and # functions as expected with caching globally enabled and the specific # section caching enabled. cacheable_function = self._get_cacheable_function() self._add_test_caching_option() self.config_fixture.config(group='cache', enabled=True) self.config_fixture.config(group='cache', caching=True) cacheable_function(self.test_value) cached_value = cacheable_function(self.test_value) self.assertTrue(cached_value.cached) def test_cache_dictionary_config_builder(self): """Validate we build a sane dogpile.cache dictionary config.""" self.config_fixture.config(group='cache', config_prefix='test_prefix', backend='some_test_backend', expiration_time=86400, backend_argument=['arg1:test', 'arg2:test:test', 'arg3.invalid']) config_dict = cache.build_cache_config() self.assertEqual( CONF.cache.backend, config_dict['test_prefix.backend']) self.assertEqual( CONF.cache.expiration_time, config_dict['test_prefix.expiration_time']) self.assertEqual('test', config_dict['test_prefix.arguments.arg1']) self.assertEqual('test:test', config_dict['test_prefix.arguments.arg2']) self.assertFalse('test_prefix.arguments.arg3' in config_dict) def test_cache_debug_proxy(self): single_value = 'Test Value' single_key = 'testkey' multi_values = {'key1': 1, 'key2': 2, 'key3': 3} self.region.set(single_key, single_value) self.assertEqual(single_value, self.region.get(single_key)) self.region.delete(single_key) self.assertEqual(NO_VALUE, self.region.get(single_key)) self.region.set_multi(multi_values) cached_values = self.region.get_multi(multi_values.keys()) for value in multi_values.values(): self.assertIn(value, cached_values) self.assertEqual(len(multi_values.values()), len(cached_values)) self.region.delete_multi(multi_values.keys()) for value in self.region.get_multi(multi_values.keys()): self.assertEqual(NO_VALUE, value) def test_configure_non_region_object_raises_error(self): self.assertRaises(exception.ValidationError, cache.configure_cache_region, "bogus") class CacheNoopBackendTest(tests.TestCase): def setUp(self): super(CacheNoopBackendTest, self).setUp() self.region = cache.make_region() cache.configure_cache_region(self.region) def config_overrides(self): super(CacheNoopBackendTest, self).config_overrides() self.config_fixture.config(group='cache', backend='keystone.common.cache.noop') def test_noop_backend(self): single_value = 'Test Value' single_key = 'testkey' multi_values = {'key1': 1, 'key2': 2, 'key3': 3} self.region.set(single_key, single_value) self.assertEqual(NO_VALUE, self.region.get(single_key)) self.region.set_multi(multi_values) cached_values = self.region.get_multi(multi_values.keys()) self.assertEqual(len(cached_values), len(multi_values.values())) for value in cached_values: self.assertEqual(NO_VALUE, value) # Delete should not raise exceptions self.region.delete(single_key) self.region.delete_multi(multi_values.keys()) keystone-2014.1/keystone/tests/test_backend_rules.py0000664000175400017540000000431212323716267024026 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone import exception from keystone import tests from keystone.tests import test_backend class RulesPolicy(tests.TestCase, test_backend.PolicyTests): def setUp(self): super(RulesPolicy, self).setUp() self.load_backends() def config_overrides(self): super(RulesPolicy, self).config_overrides() self.config_fixture.config( group='policy', driver='keystone.policy.backends.rules.Policy') def test_create(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_create) def test_get(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_get) def test_list(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_list) def test_update(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_update) def test_delete(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_delete) def test_get_policy_404(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_get_policy_404) def test_update_policy_404(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_update_policy_404) def test_delete_policy_404(self): self.assertRaises(exception.NotImplemented, super(RulesPolicy, self).test_delete_policy_404) keystone-2014.1/keystone/tests/test_url_middleware.py0000664000175400017540000000374412323716267024234 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import webob from keystone import middleware from keystone import tests class FakeApp(object): """Fakes a WSGI app URL normalized.""" def __call__(self, env, start_response): resp = webob.Response() resp.body = 'SUCCESS' return resp(env, start_response) class UrlMiddlewareTest(tests.TestCase): def setUp(self): self.middleware = middleware.NormalizingFilter(FakeApp()) self.response_status = None self.response_headers = None super(UrlMiddlewareTest, self).setUp() def start_fake_response(self, status, headers): self.response_status = int(status.split(' ', 1)[0]) self.response_headers = dict(headers) def test_trailing_slash_normalization(self): """Tests /v2.0/tokens and /v2.0/tokens/ normalized URLs match.""" req1 = webob.Request.blank('/v2.0/tokens') req2 = webob.Request.blank('/v2.0/tokens/') self.middleware(req1.environ, self.start_fake_response) self.middleware(req2.environ, self.start_fake_response) self.assertEqual(req1.path_url, req2.path_url) self.assertEqual(req1.path_url, 'http://localhost/v2.0/tokens') def test_rewrite_empty_path(self): """Tests empty path is rewritten to root.""" req = webob.Request.blank('') self.middleware(req.environ, self.start_fake_response) self.assertEqual(req.path_url, 'http://localhost/') keystone-2014.1/keystone/tests/default_fixtures.py0000664000175400017540000000577312323716267023557 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. # NOTE(dolph): please try to avoid additional fixtures if possible; test suite # performance may be negatively affected. DEFAULT_DOMAIN_ID = 'default' TENANTS = [ { 'id': 'bar', 'name': 'BAR', 'domain_id': DEFAULT_DOMAIN_ID, 'description': 'description', 'enabled': True, }, { 'id': 'baz', 'name': 'BAZ', 'domain_id': DEFAULT_DOMAIN_ID, 'description': 'description', 'enabled': True, }, { 'id': 'mtu', 'name': 'MTU', 'description': 'description', 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID }, { 'id': 'service', 'name': 'service', 'description': 'description', 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID } ] # NOTE(ja): a role of keystone_admin is done in setUp USERS = [ { 'id': 'foo', 'name': 'FOO', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'foo2', 'tenants': ['bar'], 'enabled': True, 'email': 'foo@bar.com', }, { 'id': 'two', 'name': 'TWO', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'two2', 'enabled': True, 'default_project_id': 'baz', 'tenants': ['baz'], 'email': 'two@three.com', }, { 'id': 'badguy', 'name': 'BadGuy', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'bad', 'enabled': False, 'default_project_id': 'baz', 'tenants': ['baz'], 'email': 'bad@guy.com', }, { 'id': 'sna', 'name': 'SNA', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'snafu', 'enabled': True, 'tenants': ['bar'], 'email': 'sna@snl.coom', } ] ROLES = [ { 'id': 'admin', 'name': 'admin', }, { 'id': 'member', 'name': 'Member', }, { 'id': '9fe2ff9ee4384b1894a90878d3e92bab', 'name': '_member_', }, { 'id': 'other', 'name': 'Other', }, { 'id': 'browser', 'name': 'Browser', }, { 'id': 'writer', 'name': 'Writer', }, { 'id': 'service', 'name': 'Service', } ] DOMAINS = [{'description': (u'Owns users and tenants (i.e. projects)' ' available on Identity API v2.'), 'enabled': True, 'id': DEFAULT_DOMAIN_ID, 'name': u'Default'}] keystone-2014.1/keystone/tests/test_config.py0000664000175400017540000000620212323716272022466 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import uuid from keystone import config from keystone import exception from keystone import tests CONF = config.CONF class ConfigTestCase(tests.TestCase): def config_files(self): config_files = super(ConfigTestCase, self).config_files() # Insert the keystone sample as the first config file to be loaded # since it is used in one of the code paths to determine the paste-ini # location. config_files.insert(0, tests.dirs.etc('keystone.conf.sample')) return config_files def test_paste_config(self): self.assertEqual(config.find_paste_config(), tests.dirs.etc('keystone-paste.ini')) self.config_fixture.config(group='paste_deploy', config_file=uuid.uuid4().hex) self.assertRaises(exception.ConfigFileNotFound, config.find_paste_config) self.config_fixture.config(group='paste_deploy', config_file='') self.assertEqual(config.find_paste_config(), tests.dirs.etc('keystone.conf.sample')) def test_config_default(self): self.assertEqual('keystone.auth.plugins.password.Password', CONF.auth.password) self.assertEqual('keystone.auth.plugins.token.Token', CONF.auth.token) class DeprecatedTestCase(tests.TestCase): """Test using the original (deprecated) name for renamed options.""" def config_files(self): config_files = super(DeprecatedTestCase, self).config_files() config_files.append(tests.dirs.tests_conf('deprecated.conf')) return config_files def test_sql(self): # Options in [sql] were moved to [database] in Icehouse for the change # to use oslo-incubator's db.sqlalchemy.sessions. self.assertEqual(CONF.database.connection, 'sqlite://deprecated') self.assertEqual(CONF.database.idle_timeout, 54321) class DeprecatedOverrideTestCase(tests.TestCase): """Test using the deprecated AND new name for renamed options.""" def config_files(self): config_files = super(DeprecatedOverrideTestCase, self).config_files() config_files.append(tests.dirs.tests_conf('deprecated_override.conf')) return config_files def test_sql(self): # Options in [sql] were moved to [database] in Icehouse for the change # to use oslo-incubator's db.sqlalchemy.sessions. self.assertEqual(CONF.database.connection, 'sqlite://new') self.assertEqual(CONF.database.idle_timeout, 65432) keystone-2014.1/keystone/tests/test_contrib_stats_core.py0000664000175400017540000000274012323716267025116 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.contrib import stats from keystone import config from keystone import tests CONF = config.CONF class StatsContribCore(tests.TestCase): def setUp(self): super(StatsContribCore, self).setUp() self.stats_middleware = stats.StatsMiddleware(None) def test_admin_request(self): host_admin = "127.0.0.1:%s" % CONF.admin_port self.assertEqual("admin", self.stats_middleware._resolve_api(host_admin)) def test_public_request(self): host_public = "127.0.0.1:%s" % CONF.public_port self.assertEqual("public", self.stats_middleware._resolve_api(host_public)) def test_other_request(self): host_public = "127.0.0.1:%s" % CONF.public_port host_other = host_public + "1" self.assertEqual(host_other, self.stats_middleware._resolve_api(host_other)) keystone-2014.1/keystone/tests/test_content_types.py0000664000175400017540000016236312323716267024136 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import uuid import six from keystone.common import extension from keystone import config from keystone.tests import rest CONF = config.CONF class CoreApiTests(object): def assertValidError(self, error): """Applicable to XML and JSON.""" self.assertIsNotNone(error.get('code')) self.assertIsNotNone(error.get('title')) self.assertIsNotNone(error.get('message')) def assertValidVersion(self, version): """Applicable to XML and JSON. However, navigating links and media-types differs between content types so they need to be validated separately. """ self.assertIsNotNone(version) self.assertIsNotNone(version.get('id')) self.assertIsNotNone(version.get('status')) self.assertIsNotNone(version.get('updated')) def assertValidExtension(self, extension): """Applicable to XML and JSON. However, navigating extension links differs between content types. They need to be validated separately with assertValidExtensionLink. """ self.assertIsNotNone(extension) self.assertIsNotNone(extension.get('name')) self.assertIsNotNone(extension.get('namespace')) self.assertIsNotNone(extension.get('alias')) self.assertIsNotNone(extension.get('updated')) def assertValidExtensionLink(self, link): """Applicable to XML and JSON.""" self.assertIsNotNone(link.get('rel')) self.assertIsNotNone(link.get('type')) self.assertIsNotNone(link.get('href')) def assertValidTenant(self, tenant): """Applicable to XML and JSON.""" self.assertIsNotNone(tenant.get('id')) self.assertIsNotNone(tenant.get('name')) def assertValidUser(self, user): """Applicable to XML and JSON.""" self.assertIsNotNone(user.get('id')) self.assertIsNotNone(user.get('name')) def assertValidRole(self, tenant): """Applicable to XML and JSON.""" self.assertIsNotNone(tenant.get('id')) self.assertIsNotNone(tenant.get('name')) def test_public_not_found(self): r = self.public_request( path='/%s' % uuid.uuid4().hex, expected_status=404) self.assertValidErrorResponse(r) def test_admin_not_found(self): r = self.admin_request( path='/%s' % uuid.uuid4().hex, expected_status=404) self.assertValidErrorResponse(r) def test_public_multiple_choice(self): r = self.public_request(path='/', expected_status=300) self.assertValidMultipleChoiceResponse(r) def test_admin_multiple_choice(self): r = self.admin_request(path='/', expected_status=300) self.assertValidMultipleChoiceResponse(r) def test_public_version(self): r = self.public_request(path='/v2.0/') self.assertValidVersionResponse(r) def test_admin_version(self): r = self.admin_request(path='/v2.0/') self.assertValidVersionResponse(r) def test_public_extensions(self): r = self.public_request(path='/v2.0/extensions') self.assertValidExtensionListResponse(r, extension.PUBLIC_EXTENSIONS) def test_admin_extensions(self): r = self.admin_request(path='/v2.0/extensions') self.assertValidExtensionListResponse(r, extension.ADMIN_EXTENSIONS) def test_admin_extensions_404(self): self.admin_request(path='/v2.0/extensions/invalid-extension', expected_status=404) def test_public_osksadm_extension_404(self): self.public_request(path='/v2.0/extensions/OS-KSADM', expected_status=404) def test_admin_osksadm_extension(self): r = self.admin_request(path='/v2.0/extensions/OS-KSADM') self.assertValidExtensionResponse(r, extension.ADMIN_EXTENSIONS) def test_authenticate(self): r = self.public_request( method='POST', path='/v2.0/tokens', body={ 'auth': { 'passwordCredentials': { 'username': self.user_foo['name'], 'password': self.user_foo['password'], }, 'tenantId': self.tenant_bar['id'], }, }, expected_status=200) self.assertValidAuthenticationResponse(r, require_service_catalog=True) def test_authenticate_unscoped(self): r = self.public_request( method='POST', path='/v2.0/tokens', body={ 'auth': { 'passwordCredentials': { 'username': self.user_foo['name'], 'password': self.user_foo['password'], }, }, }, expected_status=200) self.assertValidAuthenticationResponse(r) def test_get_tenants_for_token(self): r = self.public_request(path='/v2.0/tenants', token=self.get_scoped_token()) self.assertValidTenantListResponse(r) def test_validate_token(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/tokens/%(token_id)s' % { 'token_id': token, }, token=token) self.assertValidAuthenticationResponse(r) def test_invalid_token_404(self): token = self.get_scoped_token() self.admin_request( path='/v2.0/tokens/%(token_id)s' % { 'token_id': 'invalid', }, token=token, expected_status=404) def test_validate_token_service_role(self): self.md_foobar = self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_service['id'], self.role_service['id']) token = self.get_scoped_token(tenant_id='service') r = self.admin_request( path='/v2.0/tokens/%s' % token, token=token) self.assertValidAuthenticationResponse(r) def test_remove_role_revokes_token(self): self.md_foobar = self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_service['id'], self.role_service['id']) token = self.get_scoped_token(tenant_id='service') r = self.admin_request( path='/v2.0/tokens/%s' % token, token=token) self.assertValidAuthenticationResponse(r) self.assignment_api.remove_role_from_user_and_project( self.user_foo['id'], self.tenant_service['id'], self.role_service['id']) r = self.admin_request( path='/v2.0/tokens/%s' % token, token=token, expected_status=401) def test_validate_token_belongs_to(self): token = self.get_scoped_token() path = ('/v2.0/tokens/%s?belongsTo=%s' % (token, self.tenant_bar['id'])) r = self.admin_request(path=path, token=token) self.assertValidAuthenticationResponse(r, require_service_catalog=True) def test_validate_token_no_belongs_to_still_returns_catalog(self): token = self.get_scoped_token() path = ('/v2.0/tokens/%s' % token) r = self.admin_request(path=path, token=token) self.assertValidAuthenticationResponse(r, require_service_catalog=True) def test_validate_token_head(self): """The same call as above, except using HEAD. There's no response to validate here, but this is included for the sake of completely covering the core API. """ token = self.get_scoped_token() self.admin_request( method='HEAD', path='/v2.0/tokens/%(token_id)s' % { 'token_id': token, }, token=token, expected_status=204) def test_endpoints(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/tokens/%(token_id)s/endpoints' % { 'token_id': token, }, token=token) self.assertValidEndpointListResponse(r) def test_get_tenant(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/tenants/%(tenant_id)s' % { 'tenant_id': self.tenant_bar['id'], }, token=token) self.assertValidTenantResponse(r) def test_get_tenant_by_name(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/tenants?name=%(tenant_name)s' % { 'tenant_name': self.tenant_bar['name'], }, token=token) self.assertValidTenantResponse(r) def test_get_user_roles(self): # The server responds with a 501 Not Implemented. See bug 933565. token = self.get_scoped_token() self.admin_request( path='/v2.0/users/%(user_id)s/roles' % { 'user_id': self.user_foo['id'], }, token=token, expected_status=501) def test_get_user_roles_with_tenant(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/tenants/%(tenant_id)s/users/%(user_id)s/roles' % { 'tenant_id': self.tenant_bar['id'], 'user_id': self.user_foo['id'], }, token=token) self.assertValidRoleListResponse(r) def test_get_user(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/users/%(user_id)s' % { 'user_id': self.user_foo['id'], }, token=token) self.assertValidUserResponse(r) def test_get_user_by_name(self): token = self.get_scoped_token() r = self.admin_request( path='/v2.0/users?name=%(user_name)s' % { 'user_name': self.user_foo['name'], }, token=token) self.assertValidUserResponse(r) def test_create_update_user_invalid_enabled_type(self): # Enforce usage of boolean for 'enabled' field in JSON and XML token = self.get_scoped_token() # Test CREATE request r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, # In XML, only "true|false" are converted to boolean. 'enabled': "False", }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, # In JSON, 0|1 are not booleans 'enabled': 0, }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) # Test UPDATE request path = '/v2.0/users/%(user_id)s' % { 'user_id': self.user_foo['id'], } r = self.admin_request( method='PUT', path=path, body={ 'user': { # In XML, only "true|false" are converted to boolean. 'enabled': "False", }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) r = self.admin_request( method='PUT', path=path, body={ 'user': { # In JSON, 0|1 are not booleans 'enabled': 1, }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) def test_error_response(self): """This triggers assertValidErrorResponse by convention.""" self.public_request(path='/v2.0/tenants', expected_status=401) def test_invalid_parameter_error_response(self): token = self.get_scoped_token() bad_body = { 'OS-KSADM:service%s' % uuid.uuid4().hex: { 'name': uuid.uuid4().hex, 'type': uuid.uuid4().hex, }, } res = self.admin_request(method='POST', path='/v2.0/OS-KSADM/services', body=bad_body, token=token, expected_status=400) self.assertValidErrorResponse(res) res = self.admin_request(method='POST', path='/v2.0/users', body=bad_body, token=token, expected_status=400) self.assertValidErrorResponse(res) def _get_user_id(self, r): """Helper method to return user ID from a response. This needs to be overridden by child classes based on their content type. """ raise NotImplementedError() def _get_role_id(self, r): """Helper method to return a role ID from a response. This needs to be overridden by child classes based on their content type. """ raise NotImplementedError() def _get_role_name(self, r): """Helper method to return role NAME from a response. This needs to be overridden by child classes based on their content type. """ raise NotImplementedError() def _get_project_id(self, r): """Helper method to return project ID from a response. This needs to be overridden by child classes based on their content type. """ raise NotImplementedError() def assertNoRoles(self, r): """Helper method to assert No Roles This needs to be overridden by child classes based on their content type. """ raise NotImplementedError() def test_update_user_tenant(self): token = self.get_scoped_token() # Create a new user r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'tenantId': self.tenant_bar['id'], 'enabled': True, }, }, token=token, expected_status=200) user_id = self._get_user_id(r.result) # Check if member_role is in tenant_bar r = self.admin_request( path='/v2.0/tenants/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': self.tenant_bar['id'], 'user_id': user_id }, token=token, expected_status=200) self.assertEqual(CONF.member_role_name, self._get_role_name(r.result)) # Create a new tenant r = self.admin_request( method='POST', path='/v2.0/tenants', body={ 'tenant': { 'name': 'test_update_user', 'description': 'A description ...', 'enabled': True, }, }, token=token, expected_status=200) project_id = self._get_project_id(r.result) # Update user's tenant r = self.admin_request( method='PUT', path='/v2.0/users/%(user_id)s' % { 'user_id': user_id, }, body={ 'user': { 'tenantId': project_id, }, }, token=token, expected_status=200) # 'member_role' should be in new_tenant r = self.admin_request( path='/v2.0/tenants/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': project_id, 'user_id': user_id }, token=token, expected_status=200) self.assertEqual('_member_', self._get_role_name(r.result)) # 'member_role' should not be in tenant_bar any more r = self.admin_request( path='/v2.0/tenants/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': self.tenant_bar['id'], 'user_id': user_id }, token=token, expected_status=200) self.assertNoRoles(r.result) def test_update_user_with_invalid_tenant(self): token = self.get_scoped_token() # Create a new user r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': 'test_invalid_tenant', 'password': uuid.uuid4().hex, 'tenantId': self.tenant_bar['id'], 'enabled': True, }, }, token=token, expected_status=200) user_id = self._get_user_id(r.result) # Update user with an invalid tenant r = self.admin_request( method='PUT', path='/v2.0/users/%(user_id)s' % { 'user_id': user_id, }, body={ 'user': { 'tenantId': 'abcde12345heha', }, }, token=token, expected_status=404) def test_update_user_with_invalid_tenant_no_prev_tenant(self): token = self.get_scoped_token() # Create a new user r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': 'test_invalid_tenant', 'password': uuid.uuid4().hex, 'enabled': True, }, }, token=token, expected_status=200) user_id = self._get_user_id(r.result) # Update user with an invalid tenant r = self.admin_request( method='PUT', path='/v2.0/users/%(user_id)s' % { 'user_id': user_id, }, body={ 'user': { 'tenantId': 'abcde12345heha', }, }, token=token, expected_status=404) def test_update_user_with_old_tenant(self): token = self.get_scoped_token() # Create a new user r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'tenantId': self.tenant_bar['id'], 'enabled': True, }, }, token=token, expected_status=200) user_id = self._get_user_id(r.result) # Check if member_role is in tenant_bar r = self.admin_request( path='/v2.0/tenants/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': self.tenant_bar['id'], 'user_id': user_id }, token=token, expected_status=200) self.assertEqual(CONF.member_role_name, self._get_role_name(r.result)) # Update user's tenant with old tenant id r = self.admin_request( method='PUT', path='/v2.0/users/%(user_id)s' % { 'user_id': user_id, }, body={ 'user': { 'tenantId': self.tenant_bar['id'], }, }, token=token, expected_status=200) # 'member_role' should still be in tenant_bar r = self.admin_request( path='/v2.0/tenants/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': self.tenant_bar['id'], 'user_id': user_id }, token=token, expected_status=200) self.assertEqual('_member_', self._get_role_name(r.result)) def test_authenticating_a_user_with_no_password(self): token = self.get_scoped_token() username = uuid.uuid4().hex # create the user self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': username, 'enabled': True, }, }, token=token) # fail to authenticate r = self.public_request( method='POST', path='/v2.0/tokens', body={ 'auth': { 'passwordCredentials': { 'username': username, 'password': 'password', }, }, }, expected_status=401) self.assertValidErrorResponse(r) def test_www_authenticate_header(self): r = self.public_request( path='/v2.0/tenants', expected_status=401) self.assertEqual('Keystone uri="http://localhost"', r.headers.get('WWW-Authenticate')) def test_www_authenticate_header_host(self): test_url = 'http://%s:4187' % uuid.uuid4().hex self.config_fixture.config(public_endpoint=test_url) r = self.public_request( path='/v2.0/tenants', expected_status=401) self.assertEqual('Keystone uri="%s"' % test_url, r.headers.get('WWW-Authenticate')) class LegacyV2UsernameTests(object): """Tests to show the broken username behavior in V2. The V2 API is documented to use `username` instead of `name`. The API forced used to use name and left the username to fall into the `extra` field. These tests ensure this behavior works so fixes to `username`/`name` will be backward compatible. """ def create_user(self, **user_attrs): """Creates a users and returns the response object. :param user_attrs: attributes added to the request body (optional) """ token = self.get_scoped_token() body = { 'user': { 'name': uuid.uuid4().hex, 'enabled': True, }, } body['user'].update(user_attrs) return self.admin_request( method='POST', path='/v2.0/users', token=token, body=body, expected_status=200) def test_create_with_extra_username(self): """The response for creating a user will contain the extra fields.""" fake_username = uuid.uuid4().hex r = self.create_user(username=fake_username) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(fake_username, user.get('username')) def test_get_returns_username_from_extra(self): """The response for getting a user will contain the extra fields.""" token = self.get_scoped_token() fake_username = uuid.uuid4().hex r = self.create_user(username=fake_username) id_ = self.get_user_attribute_from_response(r, 'id') r = self.admin_request(path='/v2.0/users/%s' % id_, token=token) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(fake_username, user.get('username')) def test_update_returns_new_username_when_adding_username(self): """The response for updating a user will contain the extra fields. This is specifically testing for updating a username when a value was not previously set. """ token = self.get_scoped_token() r = self.create_user() id_ = self.get_user_attribute_from_response(r, 'id') name = self.get_user_attribute_from_response(r, 'name') enabled = self.get_user_attribute_from_response(r, 'enabled') r = self.admin_request( method='PUT', path='/v2.0/users/%s' % id_, token=token, body={ 'user': { 'name': name, 'username': 'new_username', 'enabled': enabled, }, }, expected_status=200) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual('new_username', user.get('username')) def test_update_returns_new_username_when_updating_username(self): """The response for updating a user will contain the extra fields. This tests updating a username that was previously set. """ token = self.get_scoped_token() r = self.create_user(username='original_username') id_ = self.get_user_attribute_from_response(r, 'id') name = self.get_user_attribute_from_response(r, 'name') enabled = self.get_user_attribute_from_response(r, 'enabled') r = self.admin_request( method='PUT', path='/v2.0/users/%s' % id_, token=token, body={ 'user': { 'name': name, 'username': 'new_username', 'enabled': enabled, }, }, expected_status=200) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual('new_username', user.get('username')) def test_username_is_always_returned_create(self): """Username is set as the value of name if no username is provided. This matches the v2.0 spec where we really should be using username and not name. """ r = self.create_user() self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(user.get('name'), user.get('username')) def test_username_is_always_returned_get(self): """Username is set as the value of name if no username is provided. This matches the v2.0 spec where we really should be using username and not name. """ token = self.get_scoped_token() r = self.create_user() id_ = self.get_user_attribute_from_response(r, 'id') r = self.admin_request(path='/v2.0/users/%s' % id_, token=token) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(user.get('name'), user.get('username')) def test_username_is_always_returned_get_by_name(self): """Username is set as the value of name if no username is provided. This matches the v2.0 spec where we really should be using username and not name. """ token = self.get_scoped_token() r = self.create_user() name = self.get_user_attribute_from_response(r, 'name') r = self.admin_request(path='/v2.0/users?name=%s' % name, token=token) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(user.get('name'), user.get('username')) def test_username_is_always_returned_update_no_username_provided(self): """Username is set as the value of name if no username is provided. This matches the v2.0 spec where we really should be using username and not name. """ token = self.get_scoped_token() r = self.create_user() id_ = self.get_user_attribute_from_response(r, 'id') name = self.get_user_attribute_from_response(r, 'name') enabled = self.get_user_attribute_from_response(r, 'enabled') r = self.admin_request( method='PUT', path='/v2.0/users/%s' % id_, token=token, body={ 'user': { 'name': name, 'enabled': enabled, }, }, expected_status=200) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(user.get('name'), user.get('username')) def test_updated_username_is_returned(self): """Username is set as the value of name if no username is provided. This matches the v2.0 spec where we really should be using username and not name. """ token = self.get_scoped_token() r = self.create_user() id_ = self.get_user_attribute_from_response(r, 'id') name = self.get_user_attribute_from_response(r, 'name') enabled = self.get_user_attribute_from_response(r, 'enabled') r = self.admin_request( method='PUT', path='/v2.0/users/%s' % id_, token=token, body={ 'user': { 'name': name, 'enabled': enabled, }, }, expected_status=200) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(user.get('name'), user.get('username')) def test_username_can_be_used_instead_of_name_create(self): token = self.get_scoped_token() r = self.admin_request( method='POST', path='/v2.0/users', token=token, body={ 'user': { 'username': uuid.uuid4().hex, 'enabled': True, }, }, expected_status=200) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(user.get('name'), user.get('username')) def test_username_can_be_used_instead_of_name_update(self): token = self.get_scoped_token() r = self.create_user() id_ = self.get_user_attribute_from_response(r, 'id') new_username = uuid.uuid4().hex enabled = self.get_user_attribute_from_response(r, 'enabled') r = self.admin_request( method='PUT', path='/v2.0/users/%s' % id_, token=token, body={ 'user': { 'username': new_username, 'enabled': enabled, }, }, expected_status=200) self.assertValidUserResponse(r) user = self.get_user_from_response(r) self.assertEqual(new_username, user.get('name')) self.assertEqual(user.get('name'), user.get('username')) class RestfulTestCase(rest.RestfulTestCase): def setUp(self): super(RestfulTestCase, self).setUp() # TODO(termie): add an admin user to the fixtures and use that user # override the fixtures, for now self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_admin['id']) class JsonTestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests): content_type = 'json' def _get_user_id(self, r): return r['user']['id'] def _get_role_name(self, r): return r['roles'][0]['name'] def _get_role_id(self, r): return r['roles'][0]['id'] def _get_project_id(self, r): return r['tenant']['id'] def _get_token_id(self, r): """Applicable only to JSON.""" return r.result['access']['token']['id'] def assertNoRoles(self, r): self.assertEqual([], r['roles']) def assertValidErrorResponse(self, r): self.assertIsNotNone(r.result.get('error')) self.assertValidError(r.result['error']) self.assertEqual(r.result['error']['code'], r.status_code) def assertValidExtension(self, extension, expected): super(JsonTestCase, self).assertValidExtension(extension) descriptions = [ext['description'] for ext in six.itervalues(expected)] description = extension.get('description') self.assertIsNotNone(description) self.assertIn(description, descriptions) self.assertIsNotNone(extension.get('links')) self.assertNotEmpty(extension.get('links')) for link in extension.get('links'): self.assertValidExtensionLink(link) def assertValidExtensionListResponse(self, r, expected): self.assertIsNotNone(r.result.get('extensions')) self.assertIsNotNone(r.result['extensions'].get('values')) self.assertNotEmpty(r.result['extensions'].get('values')) for extension in r.result['extensions']['values']: self.assertValidExtension(extension, expected) def assertValidExtensionResponse(self, r, expected): self.assertValidExtension(r.result.get('extension'), expected) def assertValidUser(self, user): super(JsonTestCase, self).assertValidUser(user) self.assertNotIn('default_project_id', user) if 'tenantId' in user: # NOTE(morganfainberg): tenantId should never be "None", it gets # filtered out of the object if it is there. This is suspenders # and a belt check to avoid unintended regressions. self.assertIsNotNone(user.get('tenantId')) def assertValidAuthenticationResponse(self, r, require_service_catalog=False): self.assertIsNotNone(r.result.get('access')) self.assertIsNotNone(r.result['access'].get('token')) self.assertIsNotNone(r.result['access'].get('user')) # validate token self.assertIsNotNone(r.result['access']['token'].get('id')) self.assertIsNotNone(r.result['access']['token'].get('expires')) tenant = r.result['access']['token'].get('tenant') if tenant is not None: # validate tenant self.assertIsNotNone(tenant.get('id')) self.assertIsNotNone(tenant.get('name')) # validate user self.assertIsNotNone(r.result['access']['user'].get('id')) self.assertIsNotNone(r.result['access']['user'].get('name')) if require_service_catalog: # roles are only provided with a service catalog roles = r.result['access']['user'].get('roles') self.assertNotEmpty(roles) for role in roles: self.assertIsNotNone(role.get('name')) serviceCatalog = r.result['access'].get('serviceCatalog') # validate service catalog if require_service_catalog: self.assertIsNotNone(serviceCatalog) if serviceCatalog is not None: self.assertIsInstance(serviceCatalog, list) if require_service_catalog: self.assertNotEmpty(serviceCatalog) for service in r.result['access']['serviceCatalog']: # validate service self.assertIsNotNone(service.get('name')) self.assertIsNotNone(service.get('type')) # services contain at least one endpoint self.assertIsNotNone(service.get('endpoints')) self.assertNotEmpty(service['endpoints']) for endpoint in service['endpoints']: # validate service endpoint self.assertIsNotNone(endpoint.get('publicURL')) def assertValidTenantListResponse(self, r): self.assertIsNotNone(r.result.get('tenants')) self.assertNotEmpty(r.result['tenants']) for tenant in r.result['tenants']: self.assertValidTenant(tenant) self.assertIsNotNone(tenant.get('enabled')) self.assertIn(tenant.get('enabled'), [True, False]) def assertValidUserResponse(self, r): self.assertIsNotNone(r.result.get('user')) self.assertValidUser(r.result['user']) def assertValidTenantResponse(self, r): self.assertIsNotNone(r.result.get('tenant')) self.assertValidTenant(r.result['tenant']) def assertValidRoleListResponse(self, r): self.assertIsNotNone(r.result.get('roles')) self.assertNotEmpty(r.result['roles']) for role in r.result['roles']: self.assertValidRole(role) def assertValidVersion(self, version): super(JsonTestCase, self).assertValidVersion(version) self.assertIsNotNone(version.get('links')) self.assertNotEmpty(version.get('links')) for link in version.get('links'): self.assertIsNotNone(link.get('rel')) self.assertIsNotNone(link.get('href')) self.assertIsNotNone(version.get('media-types')) self.assertNotEmpty(version.get('media-types')) for media in version.get('media-types'): self.assertIsNotNone(media.get('base')) self.assertIsNotNone(media.get('type')) def assertValidMultipleChoiceResponse(self, r): self.assertIsNotNone(r.result.get('versions')) self.assertIsNotNone(r.result['versions'].get('values')) self.assertNotEmpty(r.result['versions']['values']) for version in r.result['versions']['values']: self.assertValidVersion(version) def assertValidVersionResponse(self, r): self.assertValidVersion(r.result.get('version')) def assertValidEndpointListResponse(self, r): self.assertIsNotNone(r.result.get('endpoints')) self.assertNotEmpty(r.result['endpoints']) for endpoint in r.result['endpoints']: self.assertIsNotNone(endpoint.get('id')) self.assertIsNotNone(endpoint.get('name')) self.assertIsNotNone(endpoint.get('type')) self.assertIsNotNone(endpoint.get('publicURL')) self.assertIsNotNone(endpoint.get('internalURL')) self.assertIsNotNone(endpoint.get('adminURL')) def get_user_from_response(self, r): return r.result.get('user') def get_user_attribute_from_response(self, r, attribute_name): return r.result['user'][attribute_name] def test_service_crud_requires_auth(self): """Service CRUD should 401 without an X-Auth-Token (bug 1006822).""" # values here don't matter because we should 401 before they're checked service_path = '/v2.0/OS-KSADM/services/%s' % uuid.uuid4().hex service_body = { 'OS-KSADM:service': { 'name': uuid.uuid4().hex, 'type': uuid.uuid4().hex, }, } r = self.admin_request(method='GET', path='/v2.0/OS-KSADM/services', expected_status=401) self.assertValidErrorResponse(r) r = self.admin_request(method='POST', path='/v2.0/OS-KSADM/services', body=service_body, expected_status=401) self.assertValidErrorResponse(r) r = self.admin_request(method='GET', path=service_path, expected_status=401) self.assertValidErrorResponse(r) r = self.admin_request(method='DELETE', path=service_path, expected_status=401) self.assertValidErrorResponse(r) def test_user_role_list_requires_auth(self): """User role list should 401 without an X-Auth-Token (bug 1006815).""" # values here don't matter because we should 401 before they're checked path = '/v2.0/tenants/%(tenant_id)s/users/%(user_id)s/roles' % { 'tenant_id': uuid.uuid4().hex, 'user_id': uuid.uuid4().hex, } r = self.admin_request(path=path, expected_status=401) self.assertValidErrorResponse(r) def test_fetch_revocation_list_nonadmin_fails(self): self.admin_request( method='GET', path='/v2.0/tokens/revoked', expected_status=401) def test_fetch_revocation_list_admin_200(self): token = self.get_scoped_token() r = self.admin_request( method='GET', path='/v2.0/tokens/revoked', token=token, expected_status=200) self.assertValidRevocationListResponse(r) def assertValidRevocationListResponse(self, response): self.assertIsNotNone(response.result['signed']) def test_create_update_user_json_invalid_enabled_type(self): # Enforce usage of boolean for 'enabled' field in JSON token = self.get_scoped_token() # Test CREATE request r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, # In JSON, "true|false" are not boolean 'enabled': "true", }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) # Test UPDATE request r = self.admin_request( method='PUT', path='/v2.0/users/%(user_id)s' % { 'user_id': self.user_foo['id'], }, body={ 'user': { # In JSON, "true|false" are not boolean 'enabled': "true", }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) def test_authenticating_a_user_with_an_OSKSADM_password(self): token = self.get_scoped_token() username = uuid.uuid4().hex password = uuid.uuid4().hex # create the user r = self.admin_request( method='POST', path='/v2.0/users', body={ 'user': { 'name': username, 'OS-KSADM:password': password, 'enabled': True, }, }, token=token) # successfully authenticate self.public_request( method='POST', path='/v2.0/tokens', body={ 'auth': { 'passwordCredentials': { 'username': username, 'password': password, }, }, }, expected_status=200) # ensure password doesn't leak user_id = r.result['user']['id'] r = self.admin_request( method='GET', path='/v2.0/users/%s' % user_id, token=token, expected_status=200) self.assertNotIn('OS-KSADM:password', r.result['user']) def test_updating_a_user_with_an_OSKSADM_password(self): token = self.get_scoped_token() user_id = self.user_foo['id'] password = uuid.uuid4().hex # update the user self.admin_request( method='PUT', path='/v2.0/users/%s/OS-KSADM/password' % user_id, body={ 'user': { 'password': password, }, }, token=token, expected_status=200) # successfully authenticate self.public_request( method='POST', path='/v2.0/tokens', body={ 'auth': { 'passwordCredentials': { 'username': self.user_foo['name'], 'password': password, }, }, }, expected_status=200) class RevokeApiJsonTestCase(JsonTestCase): def config_overrides(self): super(RevokeApiJsonTestCase, self).config_overrides() self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.kvs.Revoke') self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider', revoke_by_id=False) def test_fetch_revocation_list_admin_200(self): self.skipTest('Revoke API disables revocation_list.') class XmlTestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests): xmlns = 'http://docs.openstack.org/identity/api/v2.0' content_type = 'xml' def _get_user_id(self, r): return r.get('id') def _get_role_name(self, r): return r[0].get('name') def _get_role_id(self, r): return r[0].get('id') def _get_project_id(self, r): return r.get('id') def assertNoRoles(self, r): self.assertEqual(0, len(r)) def _get_token_id(self, r): return r.result.find(self._tag('token')).get('id') def _tag(self, tag_name, xmlns=None): """Helper method to build an namespaced element name.""" return '{%(ns)s}%(tag)s' % {'ns': xmlns or self.xmlns, 'tag': tag_name} def assertValidErrorResponse(self, r): xml = r.result self.assertEqual(self._tag('error'), xml.tag) self.assertValidError(xml) self.assertEqual(str(r.status_code), xml.get('code')) def assertValidExtension(self, extension, expected): super(XmlTestCase, self).assertValidExtension(extension) self.assertIsNotNone(extension.find(self._tag('description'))) self.assertTrue(extension.find(self._tag('description')).text) links = extension.find(self._tag('links')) self.assertNotEmpty(links.findall(self._tag('link'))) descriptions = [ext['description'] for ext in six.itervalues(expected)] description = extension.find(self._tag('description')).text self.assertIn(description, descriptions) for link in links.findall(self._tag('link')): self.assertValidExtensionLink(link) def assertValidExtensionListResponse(self, r, expected): xml = r.result self.assertEqual(self._tag('extensions'), xml.tag) self.assertNotEmpty(xml.findall(self._tag('extension'))) for ext in xml.findall(self._tag('extension')): self.assertValidExtension(ext, expected) def assertValidExtensionResponse(self, r, expected): xml = r.result self.assertEqual(self._tag('extension'), xml.tag) self.assertValidExtension(xml, expected) def assertValidVersion(self, version): super(XmlTestCase, self).assertValidVersion(version) links = version.find(self._tag('links')) self.assertIsNotNone(links) self.assertNotEmpty(links.findall(self._tag('link'))) for link in links.findall(self._tag('link')): self.assertIsNotNone(link.get('rel')) self.assertIsNotNone(link.get('href')) media_types = version.find(self._tag('media-types')) self.assertIsNotNone(media_types) self.assertNotEmpty(media_types.findall(self._tag('media-type'))) for media in media_types.findall(self._tag('media-type')): self.assertIsNotNone(media.get('base')) self.assertIsNotNone(media.get('type')) def assertValidMultipleChoiceResponse(self, r): xml = r.result self.assertEqual(self._tag('versions'), xml.tag) self.assertNotEmpty(xml.findall(self._tag('version'))) for version in xml.findall(self._tag('version')): self.assertValidVersion(version) def assertValidVersionResponse(self, r): xml = r.result self.assertEqual(self._tag('version'), xml.tag) self.assertValidVersion(xml) def assertValidEndpointListResponse(self, r): xml = r.result self.assertEqual(self._tag('endpoints'), xml.tag) self.assertNotEmpty(xml.findall(self._tag('endpoint'))) for endpoint in xml.findall(self._tag('endpoint')): self.assertIsNotNone(endpoint.get('id')) self.assertIsNotNone(endpoint.get('name')) self.assertIsNotNone(endpoint.get('type')) self.assertIsNotNone(endpoint.get('publicURL')) self.assertIsNotNone(endpoint.get('internalURL')) self.assertIsNotNone(endpoint.get('adminURL')) def assertValidTenantResponse(self, r): xml = r.result self.assertEqual(self._tag('tenant'), xml.tag) self.assertValidTenant(xml) def assertValidUserResponse(self, r): xml = r.result self.assertEqual(self._tag('user'), xml.tag) self.assertValidUser(xml) def assertValidRoleListResponse(self, r): xml = r.result self.assertEqual(self._tag('roles'), xml.tag) self.assertNotEmpty(r.result.findall(self._tag('role'))) for role in r.result.findall(self._tag('role')): self.assertValidRole(role) def assertValidAuthenticationResponse(self, r, require_service_catalog=False): xml = r.result self.assertEqual(self._tag('access'), xml.tag) # validate token token = xml.find(self._tag('token')) self.assertIsNotNone(token) self.assertIsNotNone(token.get('id')) self.assertIsNotNone(token.get('expires')) tenant = token.find(self._tag('tenant')) if tenant is not None: # validate tenant self.assertValidTenant(tenant) self.assertIn(tenant.get('enabled'), ['true', 'false']) user = xml.find(self._tag('user')) self.assertIsNotNone(user) self.assertIsNotNone(user.get('id')) self.assertIsNotNone(user.get('name')) if require_service_catalog: # roles are only provided with a service catalog roles = user.findall(self._tag('role')) self.assertNotEmpty(roles) for role in roles: self.assertIsNotNone(role.get('name')) serviceCatalog = xml.find(self._tag('serviceCatalog')) # validate the serviceCatalog if require_service_catalog: self.assertIsNotNone(serviceCatalog) if serviceCatalog is not None: services = serviceCatalog.findall(self._tag('service')) if require_service_catalog: self.assertNotEmpty(services) for service in services: # validate service self.assertIsNotNone(service.get('name')) self.assertIsNotNone(service.get('type')) # services contain at least one endpoint endpoints = service.findall(self._tag('endpoint')) self.assertNotEmpty(endpoints) for endpoint in endpoints: # validate service endpoint self.assertIsNotNone(endpoint.get('publicURL')) def assertValidTenantListResponse(self, r): xml = r.result self.assertEqual(self._tag('tenants'), xml.tag) self.assertNotEmpty(r.result) for tenant in r.result.findall(self._tag('tenant')): self.assertValidTenant(tenant) self.assertIn(tenant.get('enabled'), ['true', 'false']) def get_user_from_response(self, r): return r.result def get_user_attribute_from_response(self, r, attribute_name): return r.result.get(attribute_name) def test_authenticate_with_invalid_xml_in_password(self): # public_request would auto escape the ampersand self.public_request( method='POST', path='/v2.0/tokens', headers={ 'Content-Type': 'application/xml' }, body=""" """, expected_status=400, convert=False) def test_add_tenant_xml(self): """Create a tenant without providing description field.""" token = self.get_scoped_token() r = self.admin_request( method='POST', path='/v2.0/tenants', headers={ 'Content-Type': 'application/xml', 'X-Auth-Token': token }, body=""" """, convert=False) self._from_content_type(r, 'json') self.assertIsNotNone(r.result.get('tenant')) self.assertValidTenant(r.result['tenant']) self.assertEqual("", r.result['tenant'].get('description')) def test_add_tenant_json(self): """Create a tenant without providing description field.""" token = self.get_scoped_token() r = self.admin_request( method='POST', path='/v2.0/tenants', headers={ 'Content-Type': 'application/json', 'X-Auth-Token': token }, body=""" {"tenant":{ "name":"test1", "description":"", "enabled":true} } """, convert=False) self._from_content_type(r, 'json') self.assertIsNotNone(r.result.get('tenant')) self.assertValidTenant(r.result['tenant']) self.assertEqual("", r.result['tenant'].get('description')) def test_create_project_invalid_enabled_type_string(self): # Forbidden usage of string for 'enabled' field in JSON and XML token = self.get_scoped_token() r = self.admin_request( method='POST', path='/v2.0/tenants', body={ 'tenant': { 'name': uuid.uuid4().hex, # In XML, only "true|false" are converted to boolean. 'enabled': "False", }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) def test_update_project_invalid_enabled_type_string(self): # Forbidden usage of string for 'enabled' field in JSON and XML token = self.get_scoped_token() path = '/v2.0/tenants/%(tenant_id)s' % { 'tenant_id': self.tenant_bar['id'], } r = self.admin_request( method='PUT', path=path, body={ 'tenant': { # In XML, only "true|false" are converted to boolean. 'enabled': "False", }, }, token=token, expected_status=400) self.assertValidErrorResponse(r) def test_authenticating_a_user_with_an_OSKSADM_password(self): token = self.get_scoped_token() xmlns = "http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0" username = uuid.uuid4().hex password = uuid.uuid4().hex # create the user self.admin_request( method='POST', path='/v2.0/users', headers={ 'Content-Type': 'application/xml' }, body=""" """ % dict(username=username, password=password, xmlns=xmlns), token=token, expected_status=200, convert=False) # successfully authenticate self.public_request( method='POST', path='/v2.0/tokens', headers={ 'Content-Type': 'application/xml' }, body=""" """ % dict(username=username, password=password, xmlns=xmlns), token=token, expected_status=200, convert=False) def test_remove_role_revokes_token(self): self.md_foobar = self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_service['id'], self.role_service['id']) token = self.get_scoped_token(tenant_id='service') r = self.admin_request( path='/v2.0/tokens/%s' % token, token=token) self.assertValidAuthenticationResponse(r) self.assignment_api.remove_role_from_user_and_project( self.user_foo['id'], self.tenant_service['id'], self.role_service['id']) # TODO(ayoung): test fails due to XML problem # r = self.admin_request( # path='/v2.0/tokens/%s' % token, # token=token, # expected_status=401) keystone-2014.1/keystone/tests/test_sql_livetest.py0000664000175400017540000000540212323716267023744 0ustar jenkinsjenkins00000000000000# Copyright 2013 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 keystone import config from keystone import tests from keystone.tests import test_sql_migrate_extensions from keystone.tests import test_sql_upgrade CONF = config.CONF class PostgresqlMigrateTests(test_sql_upgrade.SqlUpgradeTests): def setUp(self): self.skip_if_env_not_set('ENABLE_LIVE_POSTGRES_TEST') super(PostgresqlMigrateTests, self).setUp() def config_files(self): files = (test_sql_upgrade.SqlUpgradeTests. _config_file_list[:]) files.append(tests.dirs.tests_conf("backend_postgresql.conf")) return files class MysqlMigrateTests(test_sql_upgrade.SqlUpgradeTests): def setUp(self): self.skip_if_env_not_set('ENABLE_LIVE_MYSQL_TEST') super(MysqlMigrateTests, self).setUp() def config_files(self): files = (test_sql_upgrade.SqlUpgradeTests. _config_file_list[:]) files.append(tests.dirs.tests_conf("backend_mysql.conf")) return files class PostgresqlRevokeExtensionsTests( test_sql_migrate_extensions.RevokeExtension): def setUp(self): self.skip_if_env_not_set('ENABLE_LIVE_POSTGRES_TEST') super(PostgresqlRevokeExtensionsTests, self).setUp() def config_files(self): files = (test_sql_upgrade.SqlUpgradeTests. _config_file_list[:]) files.append(tests.dirs.tests_conf("backend_postgresql.conf")) return files class MysqlRevokeExtensionsTests(test_sql_migrate_extensions.RevokeExtension): def setUp(self): self.skip_if_env_not_set('ENABLE_LIVE_MYSQL_TEST') super(MysqlRevokeExtensionsTests, self).setUp() def config_files(self): files = (test_sql_upgrade.SqlUpgradeTests. _config_file_list[:]) files.append(tests.dirs.tests_conf("backend_mysql.conf")) return files class Db2MigrateTests(test_sql_upgrade.SqlUpgradeTests): def setUp(self): self.skip_if_env_not_set('ENABLE_LIVE_DB2_TEST') super(Db2MigrateTests, self).setUp() def config_files(self): files = (test_sql_upgrade.SqlUpgradeTests. _config_file_list[:]) files.append(tests.dirs.tests_conf("backend_db2.conf")) return files keystone-2014.1/keystone/tests/default_catalog.templates0000664000175400017540000000151712323716267024656 0ustar jenkinsjenkins00000000000000# config for templated.Catalog, using camelCase because I don't want to do # translations for keystone compat catalog.RegionOne.identity.publicURL = http://localhost:$(public_port)s/v2.0 catalog.RegionOne.identity.adminURL = http://localhost:$(admin_port)s/v2.0 catalog.RegionOne.identity.internalURL = http://localhost:$(admin_port)s/v2.0 catalog.RegionOne.identity.name = 'Identity Service' catalog.RegionOne.identity.id = 1 # fake compute service for now to help novaclient tests work catalog.RegionOne.compute.publicURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s catalog.RegionOne.compute.adminURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s catalog.RegionOne.compute.name = 'Compute Service' catalog.RegionOne.compute.id = 2 keystone-2014.1/keystone/tests/test_v3_oauth1.py0000664000175400017540000006227512323716272023046 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import copy import uuid from six.moves import urllib from keystone.common import sql from keystone.common.sql import migration_helpers from keystone import config from keystone import contrib from keystone.contrib import oauth1 from keystone.contrib.oauth1 import controllers from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common import importutils from keystone.tests import test_v3 CONF = config.CONF class OAuth1Tests(test_v3.RestfulTestCase): EXTENSION_NAME = 'oauth1' EXTENSION_TO_ADD = 'oauth1_extension' CONSUMER_URL = '/OS-OAUTH1/consumers' def setup_database(self): super(OAuth1Tests, self).setup_database() package_name = '.'.join((contrib.__name__, self.EXTENSION_NAME)) package = importutils.import_module(package_name) abs_path = migration_helpers.find_migrate_repo(package) migration.db_version_control(sql.get_engine(), abs_path) migration.db_sync(sql.get_engine(), abs_path) def setUp(self): super(OAuth1Tests, self).setUp() # Now that the app has been served, we can query CONF values self.base_url = 'http://localhost/v3' self.controller = controllers.OAuthControllerV3() def _create_single_consumer(self): ref = {'description': uuid.uuid4().hex} resp = self.post( self.CONSUMER_URL, body={'consumer': ref}) return resp.result['consumer'] def _create_request_token(self, consumer, project_id): endpoint = '/OS-OAUTH1/request_token' client = oauth1.Client(consumer['key'], client_secret=consumer['secret'], signature_method=oauth1.SIG_HMAC, callback_uri="oob") headers = {'requested_project_id': project_id} url, headers, body = client.sign(self.base_url + endpoint, http_method='POST', headers=headers) return endpoint, headers def _create_access_token(self, consumer, token): endpoint = '/OS-OAUTH1/access_token' client = oauth1.Client(consumer['key'], client_secret=consumer['secret'], resource_owner_key=token.key, resource_owner_secret=token.secret, signature_method=oauth1.SIG_HMAC, verifier=token.verifier) url, headers, body = client.sign(self.base_url + endpoint, http_method='POST') headers.update({'Content-Type': 'application/json'}) return endpoint, headers def _get_oauth_token(self, consumer, token): client = oauth1.Client(consumer['key'], client_secret=consumer['secret'], resource_owner_key=token.key, resource_owner_secret=token.secret, signature_method=oauth1.SIG_HMAC) endpoint = '/auth/tokens' url, headers, body = client.sign(self.base_url + endpoint, http_method='POST') headers.update({'Content-Type': 'application/json'}) ref = {'auth': {'identity': {'oauth1': {}, 'methods': ['oauth1']}}} return endpoint, headers, ref def _authorize_request_token(self, request_id): return '/OS-OAUTH1/authorize/%s' % (request_id) class ConsumerCRUDTests(OAuth1Tests): def _consumer_create(self, description=None, description_flag=True, **kwargs): if description_flag: ref = {'description': description} else: ref = {} if kwargs: ref.update(kwargs) resp = self.post( self.CONSUMER_URL, body={'consumer': ref}) consumer = resp.result['consumer'] consumer_id = consumer['id'] self.assertEqual(consumer['description'], description) self.assertIsNotNone(consumer_id) self.assertIsNotNone(consumer['secret']) return consumer def test_consumer_create(self): description = uuid.uuid4().hex self._consumer_create(description=description) def test_consumer_create_none_desc_1(self): self._consumer_create() def test_consumer_create_none_desc_2(self): self._consumer_create(description_flag=False) def test_consumer_create_normalize_field(self): # If create a consumer with a field with : or - in the name, # the name is normalized by converting those chars to _. field_name = 'some:weird-field' field_value = uuid.uuid4().hex extra_fields = {field_name: field_value} consumer = self._consumer_create(**extra_fields) normalized_field_name = 'some_weird_field' self.assertEqual(field_value, consumer[normalized_field_name]) def test_consumer_delete(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] resp = self.delete(self.CONSUMER_URL + '/%s' % consumer_id) self.assertResponseStatus(resp, 204) def test_consumer_get(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] resp = self.get(self.CONSUMER_URL + '/%s' % consumer_id) self_url = ['http://localhost/v3', self.CONSUMER_URL, '/', consumer_id] self_url = ''.join(self_url) self.assertEqual(resp.result['consumer']['links']['self'], self_url) self.assertEqual(resp.result['consumer']['id'], consumer_id) def test_consumer_list(self): self._consumer_create() resp = self.get(self.CONSUMER_URL) entities = resp.result['consumers'] self.assertIsNotNone(entities) self_url = ['http://localhost/v3', self.CONSUMER_URL] self_url = ''.join(self_url) self.assertEqual(resp.result['links']['self'], self_url) self.assertValidListLinks(resp.result['links']) def test_consumer_update(self): consumer = self._create_single_consumer() original_id = consumer['id'] original_description = consumer['description'] update_description = original_description + '_new' update_ref = {'description': update_description} update_resp = self.patch(self.CONSUMER_URL + '/%s' % original_id, body={'consumer': update_ref}) consumer = update_resp.result['consumer'] self.assertEqual(consumer['description'], update_description) self.assertEqual(consumer['id'], original_id) def test_consumer_update_bad_secret(self): consumer = self._create_single_consumer() original_id = consumer['id'] update_ref = copy.deepcopy(consumer) update_ref['description'] = uuid.uuid4().hex update_ref['secret'] = uuid.uuid4().hex self.patch(self.CONSUMER_URL + '/%s' % original_id, body={'consumer': update_ref}, expected_status=400) def test_consumer_update_bad_id(self): consumer = self._create_single_consumer() original_id = consumer['id'] original_description = consumer['description'] update_description = original_description + "_new" update_ref = copy.deepcopy(consumer) update_ref['description'] = update_description update_ref['id'] = update_description self.patch(self.CONSUMER_URL + '/%s' % original_id, body={'consumer': update_ref}, expected_status=400) def test_consumer_update_normalize_field(self): # If update a consumer with a field with : or - in the name, # the name is normalized by converting those chars to _. field1_name = 'some:weird-field' field1_orig_value = uuid.uuid4().hex extra_fields = {field1_name: field1_orig_value} consumer = self._consumer_create(**extra_fields) consumer_id = consumer['id'] field1_new_value = uuid.uuid4().hex field2_name = 'weird:some-field' field2_value = uuid.uuid4().hex update_ref = {field1_name: field1_new_value, field2_name: field2_value} update_resp = self.patch(self.CONSUMER_URL + '/%s' % consumer_id, body={'consumer': update_ref}) consumer = update_resp.result['consumer'] normalized_field1_name = 'some_weird_field' self.assertEqual(field1_new_value, consumer[normalized_field1_name]) normalized_field2_name = 'weird_some_field' self.assertEqual(field2_value, consumer[normalized_field2_name]) def test_consumer_create_no_description(self): resp = self.post(self.CONSUMER_URL, body={'consumer': {}}) consumer = resp.result['consumer'] consumer_id = consumer['id'] self.assertIsNone(consumer['description']) self.assertIsNotNone(consumer_id) self.assertIsNotNone(consumer['secret']) def test_consumer_get_bad_id(self): self.get(self.CONSUMER_URL + '/%(consumer_id)s' % {'consumer_id': uuid.uuid4().hex}, expected_status=404) class OAuthFlowTests(OAuth1Tests): def test_oauth_flow(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer_secret = consumer['secret'] self.consumer = {'key': consumer_id, 'secret': consumer_secret} self.assertIsNotNone(self.consumer['secret']) url, headers = self._create_request_token(self.consumer, self.project_id) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) request_key = credentials['oauth_token'][0] request_secret = credentials['oauth_token_secret'][0] self.request_token = oauth1.Token(request_key, request_secret) self.assertIsNotNone(self.request_token.key) url = self._authorize_request_token(request_key) body = {'roles': [{'id': self.role_id}]} resp = self.put(url, body=body, expected_status=200) self.verifier = resp.result['token']['oauth_verifier'] self.request_token.set_verifier(self.verifier) url, headers = self._create_access_token(self.consumer, self.request_token) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) access_key = credentials['oauth_token'][0] access_secret = credentials['oauth_token_secret'][0] self.access_token = oauth1.Token(access_key, access_secret) self.assertIsNotNone(self.access_token.key) url, headers, body = self._get_oauth_token(self.consumer, self.access_token) content = self.post(url, headers=headers, body=body) self.keystone_token_id = content.headers['X-Subject-Token'] self.keystone_token = content.result['token'] self.assertIsNotNone(self.keystone_token_id) class AccessTokenCRUDTests(OAuthFlowTests): def test_delete_access_token_dne(self): self.delete('/users/%(user)s/OS-OAUTH1/access_tokens/%(auth)s' % {'user': self.user_id, 'auth': uuid.uuid4().hex}, expected_status=404) def test_list_no_access_tokens(self): resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens' % {'user_id': self.user_id}) entities = resp.result['access_tokens'] self.assertEqual([], entities) self.assertValidListLinks(resp.result['links']) def test_get_single_access_token(self): self.test_oauth_flow() resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens/%(key)s' % {'user_id': self.user_id, 'key': self.access_token.key}) entity = resp.result['access_token'] self.assertEqual(entity['id'], self.access_token.key) self.assertEqual(entity['consumer_id'], self.consumer['key']) def test_get_access_token_dne(self): self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens/%(key)s' % {'user_id': self.user_id, 'key': uuid.uuid4().hex}, expected_status=404) def test_list_all_roles_in_access_token(self): self.test_oauth_flow() resp = self.get('/users/%(id)s/OS-OAUTH1/access_tokens/%(key)s/roles' % {'id': self.user_id, 'key': self.access_token.key}) entities = resp.result['roles'] self.assertTrue(entities) self.assertValidListLinks(resp.result['links']) def test_get_role_in_access_token(self): self.test_oauth_flow() url = ('/users/%(id)s/OS-OAUTH1/access_tokens/%(key)s/roles/%(role)s' % {'id': self.user_id, 'key': self.access_token.key, 'role': self.role_id}) resp = self.get(url) entity = resp.result['role'] self.assertEqual(entity['id'], self.role_id) def test_get_role_in_access_token_dne(self): self.test_oauth_flow() url = ('/users/%(id)s/OS-OAUTH1/access_tokens/%(key)s/roles/%(role)s' % {'id': self.user_id, 'key': self.access_token.key, 'role': uuid.uuid4().hex}) self.get(url, expected_status=404) def test_list_and_delete_access_tokens(self): self.test_oauth_flow() # List access_tokens should be > 0 resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens' % {'user_id': self.user_id}) entities = resp.result['access_tokens'] self.assertTrue(entities) self.assertValidListLinks(resp.result['links']) # Delete access_token resp = self.delete('/users/%(user)s/OS-OAUTH1/access_tokens/%(auth)s' % {'user': self.user_id, 'auth': self.access_token.key}) self.assertResponseStatus(resp, 204) # List access_token should be 0 resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens' % {'user_id': self.user_id}) entities = resp.result['access_tokens'] self.assertEqual([], entities) self.assertValidListLinks(resp.result['links']) class AuthTokenTests(OAuthFlowTests): def test_keystone_token_is_valid(self): self.test_oauth_flow() headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} r = self.get('/auth/tokens', headers=headers) self.assertValidTokenResponse(r, self.user) # now verify the oauth section oauth_section = r.result['token']['OS-OAUTH1'] self.assertEqual(oauth_section['access_token_id'], self.access_token.key) self.assertEqual(oauth_section['consumer_id'], self.consumer['key']) # verify the roles section roles_list = r.result['token']['roles'] # we can just verify the 0th role since we are only assigning one role self.assertEqual(roles_list[0]['id'], self.role_id) # verify that the token can perform delegated tasks ref = self.new_user_ref(domain_id=self.domain_id) r = self.admin_request(path='/v3/users', headers=headers, method='POST', body={'user': ref}) self.assertValidUserResponse(r, ref) def test_delete_access_token_also_revokes_token(self): self.test_oauth_flow() # Delete access token resp = self.delete('/users/%(user)s/OS-OAUTH1/access_tokens/%(auth)s' % {'user': self.user_id, 'auth': self.access_token.key}) self.assertResponseStatus(resp, 204) # Check Keystone Token no longer exists headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} self.get('/auth/tokens', headers=headers, expected_status=404) def test_deleting_consumer_also_deletes_tokens(self): self.test_oauth_flow() # Delete consumer consumer_id = self.consumer['key'] resp = self.delete('/OS-OAUTH1/consumers/%(consumer_id)s' % {'consumer_id': consumer_id}) self.assertResponseStatus(resp, 204) # List access_token should be 0 resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens' % {'user_id': self.user_id}) entities = resp.result['access_tokens'] self.assertEqual([], entities) # Check Keystone Token no longer exists headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} self.head('/auth/tokens', headers=headers, expected_status=404) def test_change_user_password_also_deletes_tokens(self): self.test_oauth_flow() # delegated keystone token exists headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} r = self.get('/auth/tokens', headers=headers) self.assertValidTokenResponse(r, self.user) user = {'password': uuid.uuid4().hex} r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body={'user': user}) headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} self.admin_request(path='/auth/tokens', headers=headers, method='GET', expected_status=404) def test_deleting_project_also_invalidates_tokens(self): self.test_oauth_flow() # delegated keystone token exists headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} r = self.get('/auth/tokens', headers=headers) self.assertValidTokenResponse(r, self.user) r = self.delete('/projects/%(project_id)s' % { 'project_id': self.project_id}) headers = {'X-Subject-Token': self.keystone_token_id, 'X-Auth-Token': self.keystone_token_id} self.admin_request(path='/auth/tokens', headers=headers, method='GET', expected_status=404) def test_token_chaining_is_not_allowed(self): self.test_oauth_flow() #attempt to re-authenticate (token chain) with the given token path = '/v3/auth/tokens/' auth_data = self.build_authentication_request( token=self.keystone_token_id) self.admin_request( path=path, body=auth_data, token=self.keystone_token_id, method='POST', expected_status=403) def test_delete_keystone_tokens_by_consumer_id(self): self.test_oauth_flow() self.token_api.get_token(self.keystone_token_id) self.token_api.delete_tokens(self.user_id, consumer_id=self.consumer['key']) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, self.keystone_token_id) class MaliciousOAuth1Tests(OAuth1Tests): def test_bad_consumer_secret(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer = {'key': consumer_id, 'secret': uuid.uuid4().hex} url, headers = self._create_request_token(consumer, self.project_id) self.post(url, headers=headers, expected_status=401) def test_bad_request_token_key(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer_secret = consumer['secret'] consumer = {'key': consumer_id, 'secret': consumer_secret} url, headers = self._create_request_token(consumer, self.project_id) self.post(url, headers=headers) url = self._authorize_request_token(uuid.uuid4().hex) body = {'roles': [{'id': self.role_id}]} self.put(url, body=body, expected_status=404) def test_bad_verifier(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer_secret = consumer['secret'] consumer = {'key': consumer_id, 'secret': consumer_secret} url, headers = self._create_request_token(consumer, self.project_id) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) request_key = credentials['oauth_token'][0] request_secret = credentials['oauth_token_secret'][0] request_token = oauth1.Token(request_key, request_secret) url = self._authorize_request_token(request_key) body = {'roles': [{'id': self.role_id}]} resp = self.put(url, body=body, expected_status=200) verifier = resp.result['token']['oauth_verifier'] self.assertIsNotNone(verifier) request_token.set_verifier(uuid.uuid4().hex) url, headers = self._create_access_token(consumer, request_token) self.post(url, headers=headers, expected_status=401) def test_bad_authorizing_roles(self): consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer_secret = consumer['secret'] consumer = {'key': consumer_id, 'secret': consumer_secret} url, headers = self._create_request_token(consumer, self.project_id) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) request_key = credentials['oauth_token'][0] self.assignment_api.remove_role_from_user_and_project( self.user_id, self.project_id, self.role_id) url = self._authorize_request_token(request_key) body = {'roles': [{'id': self.role_id}]} self.admin_request(path=url, method='PUT', body=body, expected_status=404) def test_expired_authorizing_request_token(self): CONF.oauth1.request_token_duration = -1 consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer_secret = consumer['secret'] self.consumer = {'key': consumer_id, 'secret': consumer_secret} self.assertIsNotNone(self.consumer['key']) url, headers = self._create_request_token(self.consumer, self.project_id) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) request_key = credentials['oauth_token'][0] request_secret = credentials['oauth_token_secret'][0] self.request_token = oauth1.Token(request_key, request_secret) self.assertIsNotNone(self.request_token.key) url = self._authorize_request_token(request_key) body = {'roles': [{'id': self.role_id}]} self.put(url, body=body, expected_status=401) def test_expired_creating_keystone_token(self): CONF.oauth1.access_token_duration = -1 consumer = self._create_single_consumer() consumer_id = consumer['id'] consumer_secret = consumer['secret'] self.consumer = {'key': consumer_id, 'secret': consumer_secret} self.assertIsNotNone(self.consumer['key']) url, headers = self._create_request_token(self.consumer, self.project_id) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) request_key = credentials['oauth_token'][0] request_secret = credentials['oauth_token_secret'][0] self.request_token = oauth1.Token(request_key, request_secret) self.assertIsNotNone(self.request_token.key) url = self._authorize_request_token(request_key) body = {'roles': [{'id': self.role_id}]} resp = self.put(url, body=body, expected_status=200) self.verifier = resp.result['token']['oauth_verifier'] self.request_token.set_verifier(self.verifier) url, headers = self._create_access_token(self.consumer, self.request_token) content = self.post(url, headers=headers) credentials = urllib.parse.parse_qs(content.result) access_key = credentials['oauth_token'][0] access_secret = credentials['oauth_token_secret'][0] self.access_token = oauth1.Token(access_key, access_secret) self.assertIsNotNone(self.access_token.key) url, headers, body = self._get_oauth_token(self.consumer, self.access_token) self.post(url, headers=headers, body=body, expected_status=401) keystone-2014.1/keystone/tests/test_v3_protection.py0000664000175400017540000006620212323716272024025 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import tempfile import uuid from keystone import config from keystone import exception from keystone.openstack.common import jsonutils from keystone.policy.backends import rules from keystone import tests from keystone.tests import test_v3 CONF = config.CONF DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id class IdentityTestProtectedCase(test_v3.RestfulTestCase): """Test policy enforcement on the v3 Identity API.""" def setUp(self): """Setup for Identity Protection Test Cases. As well as the usual housekeeping, create a set of domains, users, roles and projects for the subsequent tests: - Three domains: A,B & C. C is disabled. - DomainA has user1, DomainB has user2 and user3 - DomainA has group1 and group2, DomainB has group3 - User1 has two roles on DomainA - User2 has one role on DomainA Remember that there will also be a fourth domain in existence, the default domain. """ # Ensure that test_v3.RestfulTestCase doesn't load its own # sample data, which would make checking the results of our # tests harder super(IdentityTestProtectedCase, self).setUp() # Initialize the policy engine and allow us to write to a temp # file in each test to create the policies self.addCleanup(rules.reset) rules.reset() _unused, self.tmpfilename = tempfile.mkstemp() self.config_fixture.config(policy_file=self.tmpfilename) # A default auth request we can use - un-scoped user token self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password']) def load_sample_data(self): # Start by creating a couple of domains self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.domainC = self.new_domain_ref() self.domainC['enabled'] = False self.assignment_api.create_domain(self.domainC['id'], self.domainC) # Now create some users, one in domainA and two of them in domainB self.user1 = self.new_user_ref(domain_id=self.domainA['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref(domain_id=self.domainB['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user2['id'], self.user2) self.user3 = self.new_user_ref(domain_id=self.domainB['id']) self.user3['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user3['id'], self.user3) self.group1 = self.new_group_ref(domain_id=self.domainA['id']) self.identity_api.create_group(self.group1['id'], self.group1) self.group2 = self.new_group_ref(domain_id=self.domainA['id']) self.identity_api.create_group(self.group2['id'], self.group2) self.group3 = self.new_group_ref(domain_id=self.domainB['id']) self.identity_api.create_group(self.group3['id'], self.group3) self.role = self.new_role_ref() self.assignment_api.create_role(self.role['id'], self.role) self.role1 = self.new_role_ref() self.assignment_api.create_role(self.role1['id'], self.role1) self.assignment_api.create_grant(self.role['id'], user_id=self.user1['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role['id'], user_id=self.user2['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role1['id'], user_id=self.user1['id'], domain_id=self.domainA['id']) def _get_id_list_from_ref_list(self, ref_list): result_list = [] for x in ref_list: result_list.append(x['id']) return result_list def _set_policy(self, new_policy): with open(self.tmpfilename, "w") as policyfile: policyfile.write(jsonutils.dumps(new_policy)) def test_list_users_unprotected(self): """GET /users (unprotected) Test Plan: - Update policy so api is unprotected - Use an un-scoped token to make sure we can get back all the users independent of domain """ self._set_policy({"identity:list_users": []}) r = self.get('/users', auth=self.auth) id_list = self._get_id_list_from_ref_list(r.result.get('users')) self.assertIn(self.user1['id'], id_list) self.assertIn(self.user2['id'], id_list) self.assertIn(self.user3['id'], id_list) def test_list_users_filtered_by_domain(self): """GET /users?domain_id=mydomain (filtered) Test Plan: - Update policy so api is unprotected - Use an un-scoped token to make sure we can filter the users by domainB, getting back the 2 users in that domain """ self._set_policy({"identity:list_users": []}) url_by_name = '/users?domain_id=%s' % self.domainB['id'] r = self.get(url_by_name, auth=self.auth) # We should get back two users, those in DomainB id_list = self._get_id_list_from_ref_list(r.result.get('users')) self.assertIn(self.user2['id'], id_list) self.assertIn(self.user3['id'], id_list) def test_get_user_protected_match_id(self): """GET /users/{id} (match payload) Test Plan: - Update policy to protect api by user_id - List users with user_id of user1 as filter, to check that this will correctly match user_id in the flattened payload """ # TODO(henry-nash, ayoung): It would be good to expand this # test for further test flattening, e.g. protect on, say, an # attribute of an object being created new_policy = {"identity:get_user": [["user_id:%(user_id)s"]]} self._set_policy(new_policy) url_by_name = '/users/%s' % self.user1['id'] r = self.get(url_by_name, auth=self.auth) self.assertEqual(self.user1['id'], r.result['user']['id']) def test_get_user_protected_match_target(self): """GET /users/{id} (match target) Test Plan: - Update policy to protect api by domain_id - Try and read a user who is in DomainB with a token scoped to Domain A - this should fail - Retry this for a user who is in Domain A, which should succeed. - Finally, try getting a user that does not exist, which should still return UserNotFound """ new_policy = {'identity:get_user': [["domain_id:%(target.user.domain_id)s"]]} self._set_policy(new_policy) self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], domain_id=self.domainA['id']) url_by_name = '/users/%s' % self.user2['id'] r = self.get(url_by_name, auth=self.auth, expected_status=exception.ForbiddenAction.code) url_by_name = '/users/%s' % self.user1['id'] r = self.get(url_by_name, auth=self.auth) self.assertEqual(self.user1['id'], r.result['user']['id']) url_by_name = '/users/%s' % uuid.uuid4().hex r = self.get(url_by_name, auth=self.auth, expected_status=exception.UserNotFound.code) def test_revoke_grant_protected_match_target(self): """DELETE /domains/{id}/users/{id}/roles/{id} (match target) Test Plan: - Update policy to protect api by domain_id of entities in the grant - Try and delete the existing grant that has a user who is from a different domain - this should fail. - Retry this for a user who is in Domain A, which should succeed. """ new_policy = {'identity:revoke_grant': [["domain_id:%(target.user.domain_id)s"]]} self._set_policy(new_policy) collection_url = ( '/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': self.domainA['id'], 'user_id': self.user2['id']}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role['id']} self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], domain_id=self.domainA['id']) self.delete(member_url, auth=self.auth, expected_status=exception.ForbiddenAction.code) collection_url = ( '/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': self.domainA['id'], 'user_id': self.user1['id']}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role1['id']} self.delete(member_url, auth=self.auth) def test_list_users_protected_by_domain(self): """GET /users?domain_id=mydomain (protected) Test Plan: - Update policy to protect api by domain_id - List groups using a token scoped to domainA with a filter specifying domainA - we should only get back the one user that is in domainA. - Try and read the users from domainB - this should fail since we don't have a token scoped for domainB """ new_policy = {"identity:list_users": ["domain_id:%(domain_id)s"]} self._set_policy(new_policy) self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], domain_id=self.domainA['id']) url_by_name = '/users?domain_id=%s' % self.domainA['id'] r = self.get(url_by_name, auth=self.auth) # We should only get back one user, the one in DomainA id_list = self._get_id_list_from_ref_list(r.result.get('users')) self.assertEqual(1, len(id_list)) self.assertIn(self.user1['id'], id_list) # Now try for domainB, which should fail url_by_name = '/users?domain_id=%s' % self.domainB['id'] r = self.get(url_by_name, auth=self.auth, expected_status=exception.ForbiddenAction.code) def test_list_groups_protected_by_domain(self): """GET /groups?domain_id=mydomain (protected) Test Plan: - Update policy to protect api by domain_id - List groups using a token scoped to domainA and make sure we only get back the two groups that are in domainA - Try and read the groups from domainB - this should fail since we don't have a token scoped for domainB """ new_policy = {"identity:list_groups": ["domain_id:%(domain_id)s"]} self._set_policy(new_policy) self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], domain_id=self.domainA['id']) url_by_name = '/groups?domain_id=%s' % self.domainA['id'] r = self.get(url_by_name, auth=self.auth) # We should only get back two groups, the ones in DomainA id_list = self._get_id_list_from_ref_list(r.result.get('groups')) self.assertEqual(2, len(id_list)) self.assertIn(self.group1['id'], id_list) self.assertIn(self.group2['id'], id_list) # Now try for domainB, which should fail url_by_name = '/groups?domain_id=%s' % self.domainB['id'] r = self.get(url_by_name, auth=self.auth, expected_status=exception.ForbiddenAction.code) def test_list_groups_protected_by_domain_and_filtered(self): """GET /groups?domain_id=mydomain&name=myname (protected) Test Plan: - Update policy to protect api by domain_id - List groups using a token scoped to domainA with a filter specifying both domainA and the name of group. - We should only get back the group in domainA that matches the name """ new_policy = {"identity:list_groups": ["domain_id:%(domain_id)s"]} self._set_policy(new_policy) self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], domain_id=self.domainA['id']) url_by_name = '/groups?domain_id=%s&name=%s' % ( self.domainA['id'], self.group2['name']) r = self.get(url_by_name, auth=self.auth) # We should only get back one user, the one in DomainA that matches # the name supplied id_list = self._get_id_list_from_ref_list(r.result.get('groups')) self.assertEqual(1, len(id_list)) self.assertIn(self.group2['id'], id_list) class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase): """Test policy enforcement of the sample v3 cloud policy file.""" def setUp(self): """Setup for v3 Cloud Policy Sample Test Cases. The following data is created: - Three domains: domainA, domainB and admin_domain - One project, which name is 'project' - domainA has three users: domain_admin_user, project_admin_user and just_a_user: - domain_admin_user has role 'admin' on domainA, - project_admin_user has role 'admin' on the project, - just_a_user has a non-admin role on both domainA and the project. - admin_domain has user cloud_admin_user, with an 'admin' role on admin_domain. We test various api protection rules from the cloud sample policy file to make sure the sample is valid and that we correctly enforce it. """ # Ensure that test_v3.RestfulTestCase doesn't load its own # sample data, which would make checking the results of our # tests harder super(IdentityTestv3CloudPolicySample, self).setUp() # Finally, switch to the v3 sample policy file self.addCleanup(rules.reset) rules.reset() self.config_fixture.config( policy_file=tests.dirs.etc('policy.v3cloudsample.json')) def load_sample_data(self): # Start by creating a couple of domains self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.admin_domain = {'id': 'admin_domain_id', 'name': 'Admin_domain'} self.assignment_api.create_domain(self.admin_domain['id'], self.admin_domain) # And our users self.cloud_admin_user = self.new_user_ref( domain_id=self.admin_domain['id']) self.cloud_admin_user['password'] = uuid.uuid4().hex self.identity_api.create_user(self.cloud_admin_user['id'], self.cloud_admin_user) self.just_a_user = self.new_user_ref(domain_id=self.domainA['id']) self.just_a_user['password'] = uuid.uuid4().hex self.identity_api.create_user(self.just_a_user['id'], self.just_a_user) self.domain_admin_user = self.new_user_ref( domain_id=self.domainA['id']) self.domain_admin_user['password'] = uuid.uuid4().hex self.identity_api.create_user(self.domain_admin_user['id'], self.domain_admin_user) self.project_admin_user = self.new_user_ref( domain_id=self.domainA['id']) self.project_admin_user['password'] = uuid.uuid4().hex self.identity_api.create_user(self.project_admin_user['id'], self.project_admin_user) # The admin role and another plain role self.admin_role = {'id': uuid.uuid4().hex, 'name': 'admin'} self.assignment_api.create_role(self.admin_role['id'], self.admin_role) self.role = self.new_role_ref() self.assignment_api.create_role(self.role['id'], self.role) # The cloud admin just gets the admin role self.assignment_api.create_grant(self.admin_role['id'], user_id=self.cloud_admin_user['id'], domain_id=self.admin_domain['id']) # Assign roles to the domain self.assignment_api.create_grant(self.admin_role['id'], user_id=self.domain_admin_user['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role['id'], user_id=self.just_a_user['id'], domain_id=self.domainA['id']) # Create a assign roles to the project self.project = self.new_project_ref(domain_id=self.domainA['id']) self.assignment_api.create_project(self.project['id'], self.project) self.assignment_api.create_grant(self.admin_role['id'], user_id=self.project_admin_user['id'], project_id=self.project['id']) self.assignment_api.create_grant(self.role['id'], user_id=self.just_a_user['id'], project_id=self.project['id']) def _stati(self, expected_status): # Return the expected return codes for APIs with and without data # with any specified status overriding the normal values if expected_status is None: return (200, 201, 204) else: return (expected_status, expected_status, expected_status) def _test_user_management(self, domain_id, expected=None): status_OK, status_created, status_no_data = self._stati(expected) entity_url = '/users/%s' % self.just_a_user['id'] list_url = '/users?domain_id=%s' % domain_id self.get(entity_url, auth=self.auth, expected_status=status_OK) self.get(list_url, auth=self.auth, expected_status=status_OK) user = {'description': 'Updated'} self.patch(entity_url, auth=self.auth, body={'user': user}, expected_status=status_OK) self.delete(entity_url, auth=self.auth, expected_status=status_no_data) user_ref = self.new_user_ref(domain_id=domain_id) self.post('/users', auth=self.auth, body={'user': user_ref}, expected_status=status_created) def _test_project_management(self, domain_id, expected=None): status_OK, status_created, status_no_data = self._stati(expected) entity_url = '/projects/%s' % self.project['id'] list_url = '/projects?domain_id=%s' % domain_id self.get(entity_url, auth=self.auth, expected_status=status_OK) self.get(list_url, auth=self.auth, expected_status=status_OK) project = {'description': 'Updated'} self.patch(entity_url, auth=self.auth, body={'project': project}, expected_status=status_OK) self.delete(entity_url, auth=self.auth, expected_status=status_no_data) proj_ref = self.new_project_ref(domain_id=domain_id) self.post('/projects', auth=self.auth, body={'project': proj_ref}, expected_status=status_created) def _test_domain_management(self, expected=None): status_OK, status_created, status_no_data = self._stati(expected) entity_url = '/domains/%s' % self.domainB['id'] list_url = '/domains' self.get(entity_url, auth=self.auth, expected_status=status_OK) self.get(list_url, auth=self.auth, expected_status=status_OK) domain = {'description': 'Updated', 'enabled': False} self.patch(entity_url, auth=self.auth, body={'domain': domain}, expected_status=status_OK) self.delete(entity_url, auth=self.auth, expected_status=status_no_data) domain_ref = self.new_domain_ref() self.post('/domains', auth=self.auth, body={'domain': domain_ref}, expected_status=status_created) def _test_grants(self, target, entity_id, expected=None): status_OK, status_created, status_no_data = self._stati(expected) a_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(a_role['id'], a_role) collection_url = ( '/%(target)s/%(target_id)s/users/%(user_id)s/roles' % { 'target': target, 'target_id': entity_id, 'user_id': self.just_a_user['id']}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': a_role['id']} self.put(member_url, auth=self.auth, expected_status=status_no_data) self.head(member_url, auth=self.auth, expected_status=status_no_data) self.get(collection_url, auth=self.auth, expected_status=status_OK) self.delete(member_url, auth=self.auth, expected_status=status_no_data) def test_user_management(self): # First, authenticate with a user that does not have the domain # admin role - shouldn't be able to do much. self.auth = self.build_authentication_request( user_id=self.just_a_user['id'], password=self.just_a_user['password'], domain_id=self.domainA['id']) self._test_user_management( self.domainA['id'], expected=exception.ForbiddenAction.code) # Now, authenticate with a user that does have the domain admin role self.auth = self.build_authentication_request( user_id=self.domain_admin_user['id'], password=self.domain_admin_user['password'], domain_id=self.domainA['id']) self._test_user_management(self.domainA['id']) def test_user_management_by_cloud_admin(self): # Test users management with a cloud admin. This user should # be able to manage users in any domain. self.auth = self.build_authentication_request( user_id=self.cloud_admin_user['id'], password=self.cloud_admin_user['password'], domain_id=self.admin_domain['id']) self._test_user_management(self.domainA['id']) def test_project_management(self): # First, authenticate with a user that does not have the project # admin role - shouldn't be able to do much. self.auth = self.build_authentication_request( user_id=self.just_a_user['id'], password=self.just_a_user['password'], domain_id=self.domainA['id']) self._test_project_management( self.domainA['id'], expected=exception.ForbiddenAction.code) # ...but should still be able to list projects of which they are # a member url = '/users/%s/projects' % self.just_a_user['id'] self.get(url, auth=self.auth) # Now, authenticate with a user that does have the domain admin role self.auth = self.build_authentication_request( user_id=self.domain_admin_user['id'], password=self.domain_admin_user['password'], domain_id=self.domainA['id']) self._test_project_management(self.domainA['id']) def test_domain_grants(self): self.auth = self.build_authentication_request( user_id=self.just_a_user['id'], password=self.just_a_user['password'], domain_id=self.domainA['id']) self._test_grants('domains', self.domainA['id'], expected=exception.ForbiddenAction.code) # Now, authenticate with a user that does have the domain admin role self.auth = self.build_authentication_request( user_id=self.domain_admin_user['id'], password=self.domain_admin_user['password'], domain_id=self.domainA['id']) self._test_grants('domains', self.domainA['id']) # Check that with such a token we cannot modify grants on a # different domain self._test_grants('domains', self.domainB['id'], expected=exception.ForbiddenAction.code) def test_domain_grants_by_cloud_admin(self): # Test domain grants with a cloud admin. This user should be # able to manage roles on any domain. self.auth = self.build_authentication_request( user_id=self.cloud_admin_user['id'], password=self.cloud_admin_user['password'], domain_id=self.admin_domain['id']) self._test_grants('domains', self.domainA['id']) def test_project_grants(self): self.auth = self.build_authentication_request( user_id=self.just_a_user['id'], password=self.just_a_user['password'], project_id=self.project['id']) self._test_grants('projects', self.project['id'], expected=exception.ForbiddenAction.code) # Now, authenticate with a user that does have the project # admin role self.auth = self.build_authentication_request( user_id=self.project_admin_user['id'], password=self.project_admin_user['password'], project_id=self.project['id']) self._test_grants('projects', self.project['id']) def test_project_grants_by_domain_admin(self): # Test project grants with a domain admin. This user should be # able to manage roles on any project in its own domain. self.auth = self.build_authentication_request( user_id=self.domain_admin_user['id'], password=self.domain_admin_user['password'], domain_id=self.domainA['id']) self._test_grants('projects', self.project['id']) def test_cloud_admin(self): self.auth = self.build_authentication_request( user_id=self.domain_admin_user['id'], password=self.domain_admin_user['password'], domain_id=self.domainA['id']) self._test_domain_management( expected=exception.ForbiddenAction.code) self.auth = self.build_authentication_request( user_id=self.cloud_admin_user['id'], password=self.cloud_admin_user['password'], domain_id=self.admin_domain['id']) self._test_domain_management() keystone-2014.1/keystone/tests/test_backend_ldap.py0000664000175400017540000020715312323716272023620 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy import uuid import ldap from keystone import assignment from keystone.common import cache from keystone.common import ldap as common_ldap from keystone.common import sql from keystone import config from keystone import exception from keystone import identity from keystone.openstack.common.fixture import moxstubout from keystone import tests from keystone.tests import default_fixtures from keystone.tests import fakeldap from keystone.tests import test_backend CONF = config.CONF class BaseLDAPIdentity(test_backend.IdentityTests): def _get_domain_fixture(self): """Domains in LDAP are read-only, so just return the static one.""" return self.assignment_api.get_domain(CONF.identity.default_domain_id) def clear_database(self): for shelf in fakeldap.FakeShelves: fakeldap.FakeShelves[shelf].clear() def reload_backends(self, domain_id): # Only one backend unless we are using separate domain backends self.load_backends() def get_config(self, domain_id): # Only one conf structure unless we are using separate domain backends return CONF def config_overrides(self): super(BaseLDAPIdentity, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.ldap.Identity') def config_files(self): config_files = super(BaseLDAPIdentity, self).config_files() config_files.append(tests.dirs.tests_conf('backend_ldap.conf')) return config_files def test_build_tree(self): """Regression test for building the tree names """ user_api = identity.backends.ldap.UserApi(CONF) self.assertTrue(user_api) self.assertEqual("ou=Users,%s" % CONF.ldap.suffix, user_api.tree_dn) def test_configurable_allowed_user_actions(self): user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'domain_id': CONF.identity.default_domain_id, 'tenants': ['bar']} self.identity_api.create_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual('fake1', user_ref['id']) user['password'] = 'fakepass2' self.identity_api.update_user('fake1', user) self.identity_api.delete_user('fake1') self.assertRaises(exception.UserNotFound, self.identity_api.get_user, 'fake1') def test_configurable_forbidden_user_actions(self): conf = self.get_config(CONF.identity.default_domain_id) conf.ldap.user_allow_create = False conf.ldap.user_allow_update = False conf.ldap.user_allow_delete = False self.reload_backends(CONF.identity.default_domain_id) user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'domain_id': CONF.identity.default_domain_id, 'tenants': ['bar']} self.assertRaises(exception.ForbiddenAction, self.identity_api.create_user, 'fake1', user) self.user_foo['password'] = 'fakepass2' self.assertRaises(exception.ForbiddenAction, self.identity_api.update_user, self.user_foo['id'], self.user_foo) self.assertRaises(exception.ForbiddenAction, self.identity_api.delete_user, self.user_foo['id']) def test_configurable_forbidden_create_existing_user(self): conf = self.get_config(CONF.identity.default_domain_id) conf.ldap.user_allow_create = False self.reload_backends(CONF.identity.default_domain_id) self.assertRaises(exception.ForbiddenAction, self.identity_api.create_user, self.user_foo['id'], self.user_foo) def test_user_filter(self): user_ref = self.identity_api.get_user(self.user_foo['id']) self.user_foo.pop('password') self.assertDictEqual(user_ref, self.user_foo) conf = self.get_config(user_ref['domain_id']) conf.ldap.user_filter = '(CN=DOES_NOT_MATCH)' self.reload_backends(user_ref['domain_id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, self.user_foo['id']) def test_remove_role_grant_from_user_and_project(self): self.assignment_api.create_grant(user_id=self.user_foo['id'], project_id=self.tenant_baz['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_baz['id']) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(user_id=self.user_foo['id'], project_id=self.tenant_baz['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_baz['id']) self.assertEqual(0, len(roles_ref)) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, user_id=self.user_foo['id'], project_id=self.tenant_baz['id'], role_id='member') def test_get_and_remove_role_grant_by_group_and_project(self): new_domain = self._get_domain_fixture() new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], project_id=self.tenant_bar['id']) self.assertEqual([], roles_ref) self.assertEqual(0, len(roles_ref)) self.assignment_api.create_grant(group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], project_id=self.tenant_bar['id']) self.assertNotEmpty(roles_ref) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], project_id=self.tenant_bar['id']) self.assertEqual(0, len(roles_ref)) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id='member') def test_delete_user_grant_no_user(self): self.skipTest('Blocked by bug 1101287') def test_delete_group_grant_no_group(self): self.skipTest('Blocked by bug 1101287') def test_get_and_remove_role_grant_by_group_and_domain(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_get_and_remove_role_grant_by_user_and_domain(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_get_and_remove_correct_role_grant_from_a_mix(self): self.skipTest('Blocked by bug 1101287') def test_get_and_remove_role_grant_by_group_and_cross_domain(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_get_and_remove_role_grant_by_user_and_cross_domain(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_role_grant_by_group_and_cross_domain_project(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_role_grant_by_user_and_cross_domain_project(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_multi_role_grant_by_user_group_on_project_domain(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_delete_role_with_user_and_group_grants(self): self.skipTest('Blocked by bug 1101287') def test_delete_user_with_group_project_domain_links(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_delete_group_with_user_project_domain_links(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_list_projects_for_user(self): domain = self._get_domain_fixture() user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': domain['id'], 'enabled': True} self.identity_api.create_user(user1['id'], user1) user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(0, len(user_projects)) self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_bar['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_baz['id'], role_id=self.role_member['id']) user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(2, len(user_projects)) def test_list_projects_for_user_with_grants(self): domain = self._get_domain_fixture() new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.identity_api.create_group(group1['id'], group1) group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.identity_api.create_group(group2['id'], group2) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project1['id'], project1) project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project2['id'], project2) self.identity_api.add_user_to_group(new_user['id'], group1['id']) self.identity_api.add_user_to_group(new_user['id'], group2['id']) self.assignment_api.create_grant(user_id=new_user['id'], project_id=self.tenant_bar['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=new_user['id'], project_id=project1['id'], role_id=self.role_admin['id']) self.assignment_api.create_grant(group_id=group2['id'], project_id=project2['id'], role_id=self.role_admin['id']) user_projects = self.assignment_api.list_projects_for_user( new_user['id']) self.assertEqual(2, len(user_projects)) def test_create_duplicate_user_name_in_different_domains(self): self.skipTest('Blocked by bug 1101276') def test_create_duplicate_project_name_in_different_domains(self): self.skipTest('Blocked by bug 1101276') def test_create_duplicate_group_name_in_different_domains(self): self.skipTest( 'N/A: LDAP does not support multiple domains') def test_move_user_between_domains(self): self.skipTest('Blocked by bug 1101276') def test_move_user_between_domains_with_clashing_names_fails(self): self.skipTest('Blocked by bug 1101276') def test_move_group_between_domains(self): self.skipTest( 'N/A: LDAP does not support multiple domains') def test_move_group_between_domains_with_clashing_names_fails(self): self.skipTest('Blocked by bug 1101276') def test_move_project_between_domains(self): self.skipTest('Blocked by bug 1101276') def test_move_project_between_domains_with_clashing_names_fails(self): self.skipTest('Blocked by bug 1101276') def test_get_roles_for_user_and_domain(self): self.skipTest('N/A: LDAP does not support multiple domains') def test_list_role_assignments_unfiltered(self): new_domain = self._get_domain_fixture() new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': new_domain['id']} self.assignment_api.create_project(new_project['id'], new_project) # First check how many role grant already exist existing_assignments = len(self.assignment_api.list_role_assignments()) self.assignment_api.create_grant(user_id=new_user['id'], project_id=new_project['id'], role_id='other') self.assignment_api.create_grant(group_id=new_group['id'], project_id=new_project['id'], role_id='admin') # Read back the list of assignments - check it is gone up by 2 after_assignments = len(self.assignment_api.list_role_assignments()) self.assertEqual(existing_assignments + 2, after_assignments) def test_list_role_assignments_dumb_member(self): self.config_fixture.config(group='ldap', use_dumb_member=True) self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) new_domain = self._get_domain_fixture() new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) new_project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': new_domain['id']} self.assignment_api.create_project(new_project['id'], new_project) self.assignment_api.create_grant(user_id=new_user['id'], project_id=new_project['id'], role_id='other') # Read back the list of assignments and ensure # that the LDAP dumb member isn't listed. assignment_ids = [a['user_id'] for a in self.assignment_api.list_role_assignments()] dumb_id = common_ldap.BaseLdap._dn_to_id(CONF.ldap.dumb_member) self.assertNotIn(dumb_id, assignment_ids) def test_list_role_assignments_bad_role(self): self.skipTest('Blocked by bug 1221805') def test_multi_group_grants_on_project_domain(self): self.skipTest('Blocked by bug 1101287') def test_list_group_members_missing_entry(self): """List group members with deleted user. If a group has a deleted entry for a member, the non-deleted members are returned. """ # Create a group group_id = None group = dict(name=uuid.uuid4().hex, domain_id=CONF.identity.default_domain_id) group_id = self.identity_api.create_group(group_id, group)['id'] # Create a couple of users and add them to the group. user_id = None user = dict(name=uuid.uuid4().hex, id=uuid.uuid4().hex, domain_id=CONF.identity.default_domain_id) user_1_id = self.identity_api.create_user(user_id, user)['id'] self.identity_api.add_user_to_group(user_1_id, group_id) user_id = None user = dict(name=uuid.uuid4().hex, id=uuid.uuid4().hex, domain_id=CONF.identity.default_domain_id) user_2_id = self.identity_api.create_user(user_id, user)['id'] self.identity_api.add_user_to_group(user_2_id, group_id) # Delete user 2 # NOTE(blk-u): need to go directly to user interface to keep from # updating the group. driver = self.identity_api._select_identity_driver( user['domain_id']) driver.user.delete(user_2_id) # List group users and verify only user 1. res = self.identity_api.list_users_in_group(group_id) self.assertEqual(1, len(res), "Expected 1 entry (user_1)") self.assertEqual(user_1_id, res[0]['id'], "Expected user 1 id") def test_list_group_members_when_no_members(self): # List group members when there is no member in the group. # No exception should be raised. group = { 'id': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex} self.identity_api.create_group(group['id'], group) # If this doesn't raise, then the test is successful. self.identity_api.list_users_in_group(group['id']) def test_list_domains(self): domains = self.assignment_api.list_domains() self.assertEqual( [assignment.calc_default_domain()], domains) def test_list_domains_non_default_domain_id(self): # If change the default_domain_id, the ID of the default domain # returned by list_domains changes is the new default_domain_id. new_domain_id = uuid.uuid4().hex self.config_fixture.config(group='identity', default_domain_id=new_domain_id) domains = self.assignment_api.list_domains() self.assertEqual(new_domain_id, domains[0]['id']) def test_authenticate_requires_simple_bind(self): user = { 'id': 'no_meta', 'name': 'NO_META', 'domain_id': test_backend.DEFAULT_DOMAIN_ID, 'password': 'no_meta2', 'enabled': True, } self.identity_api.create_user(user['id'], user) self.assignment_api.add_user_to_project(self.tenant_baz['id'], user['id']) driver = self.identity_api._select_identity_driver( user['domain_id']) driver.user.LDAP_USER = None driver.user.LDAP_PASSWORD = None self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id=user['id'], password=None, domain_scope=user['domain_id']) # (spzala)The group and domain crud tests below override the standard ones # in test_backend.py so that we can exclude the update name test, since we # do not yet support the update of either group or domain names with LDAP. # In the tests below, the update is demonstrated by updating description. # Refer to bug 1136403 for more detail. def test_group_crud(self): group = { 'id': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex} self.identity_api.create_group(group['id'], group) group_ref = self.identity_api.get_group(group['id']) self.assertDictEqual(group_ref, group) group['description'] = uuid.uuid4().hex self.identity_api.update_group(group['id'], group) group_ref = self.identity_api.get_group(group['id']) self.assertDictEqual(group_ref, group) self.identity_api.delete_group(group['id']) self.assertRaises(exception.GroupNotFound, self.identity_api.get_group, group['id']) def test_create_user_none_mapping(self): # When create a user where an attribute maps to None, the entry is # created without that attribute and it doesn't fail with a TypeError. conf = self.get_config(CONF.identity.default_domain_id) conf.ldap.user_attribute_ignore = ['enabled', 'email', 'tenants', 'tenantId'] self.reload_backends(CONF.identity.default_domain_id) user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'domain_id': CONF.identity.default_domain_id, 'default_project_id': 'maps_to_none', } # If this doesn't raise, then the test is successful. self.identity_api.create_user('fake1', user) def test_update_user_name(self): """A user's name cannot be changed through the LDAP driver.""" self.assertRaises(exception.Conflict, super(BaseLDAPIdentity, self).test_update_user_name) def test_arbitrary_attributes_are_returned_from_create_user(self): self.skipTest("Using arbitrary attributes doesn't work under LDAP") def test_arbitrary_attributes_are_returned_from_get_user(self): self.skipTest("Using arbitrary attributes doesn't work under LDAP") def test_new_arbitrary_attributes_are_returned_from_update_user(self): self.skipTest("Using arbitrary attributes doesn't work under LDAP") def test_updated_arbitrary_attributes_are_returned_from_update_user(self): self.skipTest("Using arbitrary attributes doesn't work under LDAP") class LDAPIdentity(BaseLDAPIdentity, tests.TestCase): def setUp(self): super(LDAPIdentity, self).setUp() self.clear_database() common_ldap.register_handler('fake://', fakeldap.FakeLdap) self.load_backends() self.load_fixtures(default_fixtures) fixture = self.useFixture(moxstubout.MoxStubout()) self.mox = fixture.mox self.stubs = fixture.stubs def test_configurable_allowed_project_actions(self): tenant = {'id': 'fake1', 'name': 'fake1', 'enabled': True} self.assignment_api.create_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual('fake1', tenant_ref['id']) tenant['enabled'] = False self.assignment_api.update_project('fake1', tenant) self.assignment_api.delete_project('fake1') self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, 'fake1') def test_configurable_subtree_delete(self): self.config_fixture.config(group='ldap', allow_subtree_delete=True) self.load_backends() project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id} self.assignment_api.create_project(project1['id'], project1) role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role1['id'], role1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) self.assignment_api.add_role_to_user_and_project( user_id=user1['id'], tenant_id=project1['id'], role_id=role1['id']) self.assignment_api.delete_project(project1['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project1['id']) self.assignment_api.create_project(project1['id'], project1) list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(0, len(list)) def test_configurable_forbidden_project_actions(self): CONF.ldap.tenant_allow_create = False CONF.ldap.tenant_allow_update = False CONF.ldap.tenant_allow_delete = False self.load_backends() tenant = {'id': 'fake1', 'name': 'fake1'} self.assertRaises(exception.ForbiddenAction, self.assignment_api.create_project, 'fake1', tenant) self.tenant_bar['enabled'] = False self.assertRaises(exception.ForbiddenAction, self.assignment_api.update_project, self.tenant_bar['id'], self.tenant_bar) self.assertRaises(exception.ForbiddenAction, self.assignment_api.delete_project, self.tenant_bar['id']) def test_configurable_allowed_role_actions(self): role = {'id': 'fake1', 'name': 'fake1'} self.assignment_api.create_role('fake1', role) role_ref = self.assignment_api.get_role('fake1') self.assertEqual('fake1', role_ref['id']) role['name'] = 'fake2' self.assignment_api.update_role('fake1', role) self.assignment_api.delete_role('fake1') self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, 'fake1') def test_configurable_forbidden_role_actions(self): CONF.ldap.role_allow_create = False CONF.ldap.role_allow_update = False CONF.ldap.role_allow_delete = False self.load_backends() role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assertRaises(exception.ForbiddenAction, self.assignment_api.create_role, role['id'], role) self.role_member['name'] = uuid.uuid4().hex self.assertRaises(exception.ForbiddenAction, self.assignment_api.update_role, self.role_member['id'], self.role_member) self.assertRaises(exception.ForbiddenAction, self.assignment_api.delete_role, self.role_member['id']) def test_project_filter(self): tenant_ref = self.assignment_api.get_project(self.tenant_bar['id']) self.assertDictEqual(tenant_ref, self.tenant_bar) CONF.ldap.tenant_filter = '(CN=DOES_NOT_MATCH)' self.load_backends() # NOTE(morganfainberg): CONF.ldap.tenant_filter will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_role.invalidate(self.assignment_api, self.role_member['id']) self.assignment_api.get_role(self.role_member['id']) self.assignment_api.get_project.invalidate(self.assignment_api, self.tenant_bar['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, self.tenant_bar['id']) def test_role_filter(self): role_ref = self.assignment_api.get_role(self.role_member['id']) self.assertDictEqual(role_ref, self.role_member) CONF.ldap.role_filter = '(CN=DOES_NOT_MATCH)' self.load_backends() # NOTE(morganfainberg): CONF.ldap.role_filter will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_role.invalidate(self.assignment_api, self.role_member['id']) self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, self.role_member['id']) def test_dumb_member(self): self.config_fixture.config(group='ldap', use_dumb_member=True) self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) dumb_id = common_ldap.BaseLdap._dn_to_id(CONF.ldap.dumb_member) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, dumb_id) def test_project_attribute_mapping(self): CONF.ldap.tenant_name_attribute = 'ou' CONF.ldap.tenant_desc_attribute = 'description' CONF.ldap.tenant_enabled_attribute = 'enabled' self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) # NOTE(morganfainberg): CONF.ldap.tenant_name_attribute, # CONF.ldap.tenant_desc_attribute, and # CONF.ldap.tenant_enabled_attribute will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_project.invalidate(self.assignment_api, self.tenant_baz['id']) tenant_ref = self.assignment_api.get_project(self.tenant_baz['id']) self.assertEqual(self.tenant_baz['id'], tenant_ref['id']) self.assertEqual(self.tenant_baz['name'], tenant_ref['name']) self.assertEqual( self.tenant_baz['description'], tenant_ref['description']) self.assertEqual(self.tenant_baz['enabled'], tenant_ref['enabled']) CONF.ldap.tenant_name_attribute = 'description' CONF.ldap.tenant_desc_attribute = 'ou' self.load_backends() # NOTE(morganfainberg): CONF.ldap.tenant_name_attribute, # CONF.ldap.tenant_desc_attribute, and # CONF.ldap.tenant_enabled_attribute will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_project.invalidate(self.assignment_api, self.tenant_baz['id']) tenant_ref = self.assignment_api.get_project(self.tenant_baz['id']) self.assertEqual(self.tenant_baz['id'], tenant_ref['id']) self.assertEqual(self.tenant_baz['description'], tenant_ref['name']) self.assertEqual(self.tenant_baz['name'], tenant_ref['description']) self.assertEqual(self.tenant_baz['enabled'], tenant_ref['enabled']) def test_project_attribute_ignore(self): CONF.ldap.tenant_attribute_ignore = ['name', 'description', 'enabled'] self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) # NOTE(morganfainberg): CONF.ldap.tenant_attribute_ignore will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change configs values in tests # that could affect what the drivers would return up to the manager. # This solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_project.invalidate(self.assignment_api, self.tenant_baz['id']) tenant_ref = self.assignment_api.get_project(self.tenant_baz['id']) self.assertEqual(self.tenant_baz['id'], tenant_ref['id']) self.assertNotIn('name', tenant_ref) self.assertNotIn('description', tenant_ref) self.assertNotIn('enabled', tenant_ref) def test_role_attribute_mapping(self): CONF.ldap.role_name_attribute = 'ou' self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) # NOTE(morganfainberg): CONF.ldap.role_name_attribute will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_role.invalidate(self.assignment_api, self.role_member['id']) role_ref = self.assignment_api.get_role(self.role_member['id']) self.assertEqual(self.role_member['id'], role_ref['id']) self.assertEqual(self.role_member['name'], role_ref['name']) CONF.ldap.role_name_attribute = 'sn' self.load_backends() # NOTE(morganfainberg): CONF.ldap.role_name_attribute will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_role.invalidate(self.assignment_api, self.role_member['id']) role_ref = self.assignment_api.get_role(self.role_member['id']) self.assertEqual(self.role_member['id'], role_ref['id']) self.assertNotIn('name', role_ref) def test_role_attribute_ignore(self): CONF.ldap.role_attribute_ignore = ['name'] self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) # NOTE(morganfainberg): CONF.ldap.role_attribute_ignore will not be # dynamically changed at runtime. This invalidate is a work-around for # the expectation that it is safe to change config values in tests that # could affect what the drivers would return up to the manager. This # solves this assumption when working with aggressive (on-create) # cache population. self.assignment_api.get_role.invalidate(self.assignment_api, self.role_member['id']) role_ref = self.assignment_api.get_role(self.role_member['id']) self.assertEqual(self.role_member['id'], role_ref['id']) self.assertNotIn('name', role_ref) def test_user_enable_attribute_mask(self): CONF.ldap.user_enabled_mask = 2 CONF.ldap.user_enabled_default = '512' self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) ldap_ = self.identity_api.driver.user.get_connection() def get_enabled_vals(): user_dn = self.identity_api.driver.user._id_to_dn_string('fake1') enabled_attr_name = CONF.ldap.user_enabled_attribute res = ldap_.search_s(user_dn, ldap.SCOPE_BASE, query='(sn=fake1)') return res[0][1][enabled_attr_name] user = {'id': 'fake1', 'name': 'fake1', 'enabled': True, 'domain_id': CONF.identity.default_domain_id} user_ref = self.identity_api.create_user('fake1', user) # Use assertIs rather than assertTrue because assertIs will assert the # value is a Boolean as expected. self.assertIs(user_ref['enabled'], True) self.assertNotIn('enabled_nomask', user_ref) enabled_vals = get_enabled_vals() self.assertEqual([512], enabled_vals) user_ref = self.identity_api.get_user('fake1') self.assertIs(user_ref['enabled'], True) self.assertNotIn('enabled_nomask', user_ref) user['enabled'] = False user_ref = self.identity_api.update_user('fake1', user) self.assertIs(user_ref['enabled'], False) self.assertNotIn('enabled_nomask', user_ref) enabled_vals = get_enabled_vals() self.assertEqual([514], enabled_vals) user_ref = self.identity_api.get_user('fake1') self.assertIs(user_ref['enabled'], False) self.assertNotIn('enabled_nomask', user_ref) user['enabled'] = True user_ref = self.identity_api.update_user('fake1', user) self.assertIs(user_ref['enabled'], True) self.assertNotIn('enabled_nomask', user_ref) enabled_vals = get_enabled_vals() self.assertEqual([512], enabled_vals) user_ref = self.identity_api.get_user('fake1') self.assertIs(user_ref['enabled'], True) self.assertNotIn('enabled_nomask', user_ref) def test_user_api_get_connection_no_user_password(self): """Don't bind in case the user and password are blank.""" # Ensure the username/password are in-fact blank self.config_fixture.config(group='ldap', user=None, password=None) user_api = identity.backends.ldap.UserApi(CONF) self.stubs.Set(fakeldap, 'FakeLdap', self.mox.CreateMock(fakeldap.FakeLdap)) common_ldap.register_handler('fake://', fakeldap.FakeLdap) # we have to track all calls on 'conn' to make sure that # conn.simple_bind_s is not called conn = self.mox.CreateMockAnything() conn = fakeldap.FakeLdap(CONF.ldap.url, 0, alias_dereferencing=None, tls_cacertdir=None, tls_cacertfile=None, tls_req_cert=2, use_tls=False, chase_referrals=None).AndReturn(conn) self.mox.ReplayAll() user_api.get_connection(user=None, password=None) def test_chase_referrals_off(self): self.config_fixture.config( group='ldap', url='fake://memory', chase_referrals=False) user_api = identity.backends.ldap.UserApi(CONF) self.stubs.Set(fakeldap, 'FakeLdap', self.mox.CreateMock(fakeldap.FakeLdap)) common_ldap.register_handler('fake://', fakeldap.FakeLdap) user = uuid.uuid4().hex password = uuid.uuid4().hex conn = self.mox.CreateMockAnything() conn = fakeldap.FakeLdap(CONF.ldap.url, 0, alias_dereferencing=None, tls_cacertdir=None, tls_cacertfile=None, tls_req_cert=2, use_tls=False, chase_referrals=False).AndReturn(conn) conn.simple_bind_s(user, password).AndReturn(None) self.mox.ReplayAll() user_api.get_connection(user=user, password=password) def test_chase_referrals_on(self): self.config_fixture.config( group='ldap', url='fake://memory', chase_referrals=True) user_api = identity.backends.ldap.UserApi(CONF) self.stubs.Set(fakeldap, 'FakeLdap', self.mox.CreateMock(fakeldap.FakeLdap)) common_ldap.register_handler('fake://', fakeldap.FakeLdap) user = uuid.uuid4().hex password = uuid.uuid4().hex conn = self.mox.CreateMockAnything() conn = fakeldap.FakeLdap(CONF.ldap.url, 0, alias_dereferencing=None, tls_cacertdir=None, tls_cacertfile=None, tls_req_cert=2, use_tls=False, chase_referrals=True).AndReturn(conn) conn.simple_bind_s(user, password).AndReturn(None) self.mox.ReplayAll() user_api.get_connection(user=user, password=password) def test_wrong_ldap_scope(self): CONF.ldap.query_scope = uuid.uuid4().hex self.assertRaisesRegexp( ValueError, 'Invalid LDAP scope: %s. *' % CONF.ldap.query_scope, identity.backends.ldap.Identity) def test_wrong_alias_dereferencing(self): CONF.ldap.alias_dereferencing = uuid.uuid4().hex self.assertRaisesRegexp( ValueError, 'Invalid LDAP deref option: %s\.' % CONF.ldap.alias_dereferencing, identity.backends.ldap.Identity) def test_user_extra_attribute_mapping(self): CONF.ldap.user_additional_attribute_mapping = ['description:name'] self.load_backends() user = { 'id': 'extra_attributes', 'name': 'EXTRA_ATTRIBUTES', 'password': 'extra', 'domain_id': CONF.identity.default_domain_id } self.identity_api.create_user(user['id'], user) dn, attrs = self.identity_api.driver.user._ldap_get(user['id']) self.assertTrue(user['name'] in attrs['description']) def test_parse_extra_attribute_mapping(self): option_list = ['description:name', 'gecos:password', 'fake:invalid', 'invalid1', 'invalid2:', 'description:name:something'] mapping = self.identity_api.driver.user._parse_extra_attrs(option_list) expected_dict = {'description': 'name', 'gecos': 'password'} self.assertDictEqual(expected_dict, mapping) # TODO(henry-nash): These need to be removed when the full LDAP implementation # is submitted - see Bugs 1092187, 1101287, 1101276, 1101289 def test_domain_crud(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True, 'description': uuid.uuid4().hex} self.assertRaises(exception.Forbidden, self.assignment_api.create_domain, domain['id'], domain) self.assertRaises(exception.Conflict, self.assignment_api.create_domain, CONF.identity.default_domain_id, domain) self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, domain['id']) domain['description'] = uuid.uuid4().hex self.assertRaises(exception.DomainNotFound, self.assignment_api.update_domain, domain['id'], domain) self.assertRaises(exception.Forbidden, self.assignment_api.update_domain, CONF.identity.default_domain_id, domain) self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, domain['id']) self.assertRaises(exception.DomainNotFound, self.assignment_api.delete_domain, domain['id']) self.assertRaises(exception.Forbidden, self.assignment_api.delete_domain, CONF.identity.default_domain_id) self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, domain['id']) def test_create_domain_case_sensitivity(self): # domains are read-only, so case sensitivity isn't an issue ref = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assertRaises(exception.Forbidden, self.assignment_api.create_domain, ref['id'], ref) def test_cache_layer_domain_crud(self): # TODO(morganfainberg): This also needs to be removed when full LDAP # implementation is submitted. No need to duplicate the above test, # just skip this time. self.skipTest('Domains are read-only against LDAP') def test_project_crud(self): # NOTE(topol): LDAP implementation does not currently support the # updating of a project name so this method override # provides a different update test project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'description': uuid.uuid4().hex, 'enabled': True } self.assignment_api.create_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictEqual(project_ref, project) project['description'] = uuid.uuid4().hex self.assignment_api.update_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictEqual(project_ref, project) self.assignment_api.delete_project(project['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project['id']) @tests.skip_if_cache_disabled('assignment') def test_cache_layer_project_crud(self): # NOTE(morganfainberg): LDAP implementation does not currently support # updating project names. This method override provides a different # update test. project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'description': uuid.uuid4().hex} project_id = project['id'] # Create a project self.assignment_api.create_project(project_id, project) self.assignment_api.get_project(project_id) updated_project = copy.deepcopy(project) updated_project['description'] = uuid.uuid4().hex # Update project, bypassing assignment_api manager self.assignment_api.driver.update_project(project_id, updated_project) # Verify get_project still returns the original project_ref self.assertDictContainsSubset( project, self.assignment_api.get_project(project_id)) # Invalidate cache self.assignment_api.get_project.invalidate(self.assignment_api, project_id) # Verify get_project now returns the new project self.assertDictContainsSubset( updated_project, self.assignment_api.get_project(project_id)) # Update project using the assignment_api manager back to original self.assignment_api.update_project(project['id'], project) # Verify get_project returns the original project_ref self.assertDictContainsSubset( project, self.assignment_api.get_project(project_id)) # Delete project bypassing assignment_api self.assignment_api.driver.delete_project(project_id) # Verify get_project still returns the project_ref self.assertDictContainsSubset( project, self.assignment_api.get_project(project_id)) # Invalidate cache self.assignment_api.get_project.invalidate(self.assignment_api, project_id) # Verify ProjectNotFound now raised self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project_id) # recreate project self.assignment_api.create_project(project_id, project) self.assignment_api.get_project(project_id) # delete project self.assignment_api.delete_project(project_id) # Verify ProjectNotFound is raised self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project_id) def test_multi_role_grant_by_user_group_on_project_domain(self): # This is a partial implementation of the standard test that # is defined in test_backend.py. It omits both domain and # group grants. since neither of these are yet supported by # the ldap backend. role_list = [] for _ in range(2): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id} self.assignment_api.create_project(project1['id'], project1) self.assignment_api.add_role_to_user_and_project( user_id=user1['id'], tenant_id=project1['id'], role_id=role_list[0]['id']) self.assignment_api.add_role_to_user_and_project( user_id=user1['id'], tenant_id=project1['id'], role_id=role_list[1]['id']) # Although list_grants are not yet supported, we can test the # alternate way of getting back lists of grants, where user # and group roles are combined. Only directly assigned user # roles are available, since group grants are not yet supported combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(2, len(combined_list)) self.assertIn(role_list[0]['id'], combined_list) self.assertIn(role_list[1]['id'], combined_list) # Finally, although domain roles are not implemented, check we can # issue the combined get roles call with benign results, since thus is # used in token generation combined_role_list = self.assignment_api.get_roles_for_user_and_domain( user1['id'], CONF.identity.default_domain_id) self.assertEqual(0, len(combined_role_list)) def test_list_projects_for_alternate_domain(self): self.skipTest( 'N/A: LDAP does not support multiple domains') def test_create_grant_no_user(self): self.skipTest('Blocked by bug 1101287') def test_create_grant_no_group(self): self.skipTest('Blocked by bug 1101287') def test_get_default_domain_by_name(self): domain = self._get_domain_fixture() domain_ref = self.assignment_api.get_domain_by_name(domain['name']) self.assertEqual(domain_ref, domain) class LDAPIdentityEnabledEmulation(LDAPIdentity): def setUp(self): super(LDAPIdentityEnabledEmulation, self).setUp() self.clear_database() self.load_backends() self.load_fixtures(default_fixtures) for obj in [self.tenant_bar, self.tenant_baz, self.user_foo, self.user_two, self.user_badguy]: obj.setdefault('enabled', True) def config_files(self): config_files = super(LDAPIdentityEnabledEmulation, self).config_files() config_files.append(tests.dirs.tests_conf('backend_ldap.conf')) return config_files def config_overrides(self): super(LDAPIdentityEnabledEmulation, self).config_overrides() self.config_fixture.config(group='ldap', user_enabled_emulation=True, tenant_enabled_emulation=True) def test_project_crud(self): # NOTE(topol): LDAPIdentityEnabledEmulation will create an # enabled key in the project dictionary so this # method override handles this side-effect project = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'description': uuid.uuid4().hex} self.assignment_api.create_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) # self.assignment_api.create_project adds an enabled # key with a value of True when LDAPIdentityEnabledEmulation # is used so we now add this expected key to the project dictionary project['enabled'] = True self.assertDictEqual(project_ref, project) project['description'] = uuid.uuid4().hex self.assignment_api.update_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictEqual(project_ref, project) self.assignment_api.delete_project(project['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project['id']) def test_user_crud(self): user = { 'id': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex} self.identity_api.create_user(user['id'], user) user['enabled'] = True user_ref = self.identity_api.get_user(user['id']) del user['password'] user_ref_dict = dict((x, user_ref[x]) for x in user_ref) self.assertDictEqual(user_ref_dict, user) user['password'] = uuid.uuid4().hex self.identity_api.update_user(user['id'], user) user_ref = self.identity_api.get_user(user['id']) del user['password'] user_ref_dict = dict((x, user_ref[x]) for x in user_ref) self.assertDictEqual(user_ref_dict, user) self.identity_api.delete_user(user['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, user['id']) def test_user_enable_attribute_mask(self): self.skipTest( "Enabled emulation conflicts with enabled mask") class LdapIdentitySqlAssignment(BaseLDAPIdentity, tests.SQLDriverOverrides, tests.TestCase): def config_files(self): config_files = super(LdapIdentitySqlAssignment, self).config_files() config_files.append(tests.dirs.tests_conf('backend_ldap_sql.conf')) return config_files def setUp(self): super(LdapIdentitySqlAssignment, self).setUp() self.clear_database() self.load_backends() cache.configure_cache_region(cache.REGION) self.engine = sql.get_engine() self.addCleanup(sql.cleanup) sql.ModelBase.metadata.create_all(bind=self.engine) self.addCleanup(sql.ModelBase.metadata.drop_all, bind=self.engine) self.load_fixtures(default_fixtures) #defaulted by the data load self.user_foo['enabled'] = True def config_overrides(self): super(LdapIdentitySqlAssignment, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.ldap.Identity') self.config_fixture.config( group='assignment', driver='keystone.assignment.backends.sql.Assignment') def test_domain_crud(self): pass def test_list_domains(self): domains = self.assignment_api.list_domains() self.assertEqual([assignment.calc_default_domain()], domains) def test_list_domains_non_default_domain_id(self): # If change the default_domain_id, the ID of the default domain # returned by list_domains doesn't change because the SQL identity # backend reads it from the database, which doesn't get updated by # config change. orig_default_domain_id = CONF.identity.default_domain_id new_domain_id = uuid.uuid4().hex self.config_fixture.config(group='identity', default_domain_id=new_domain_id) domains = self.assignment_api.list_domains() self.assertEqual(orig_default_domain_id, domains[0]['id']) def test_project_filter(self): self.skipTest( 'N/A: Not part of SQL backend') def test_role_filter(self): self.skipTest( 'N/A: Not part of SQL backend') def test_add_role_grant_to_user_and_project_404(self): self.skipTest('Blocked by bug 1101287') def test_get_role_grants_for_user_and_project_404(self): self.skipTest('Blocked by bug 1101287') def test_list_projects_for_user_with_grants(self): self.skipTest('Blocked by bug 1221805') class MultiLDAPandSQLIdentity(BaseLDAPIdentity, tests.SQLDriverOverrides, tests.TestCase): """Class to test common SQL plus individual LDAP backends. We define a set of domains and domain-specific backends: - A separate LDAP backend for the default domain - A separate LDAP backend for domain1 - domain2 shares the same LDAP as domain1, but uses a different tree attach point - An SQL backend for all other domains (which will include domain3 and domain4) Normally one would expect that the default domain would be handled as part of the "other domains" - however the above provides better test coverage since most of the existing backend tests use the default domain. """ def setUp(self): super(MultiLDAPandSQLIdentity, self).setUp() self.load_backends() self.engine = sql.get_engine() self.addCleanup(sql.cleanup) sql.ModelBase.metadata.create_all(bind=self.engine) self.addCleanup(sql.ModelBase.metadata.drop_all, bind=self.engine) self._setup_domain_test_data() # All initial domain data setup complete, time to switch on support # for separate backends per domain. self.config_fixture.config(group='identity', domain_specific_drivers_enabled=True, domain_config_dir=tests.TESTSDIR) self._set_domain_configs() self.clear_database() self.load_fixtures(default_fixtures) def config_overrides(self): super(MultiLDAPandSQLIdentity, self).config_overrides() # Make sure identity and assignment are actually SQL drivers, # BaseLDAPIdentity sets these options to use LDAP. self.config_fixture.config( group='identity', driver='keystone.identity.backends.sql.Identity') self.config_fixture.config( group='assignment', driver='keystone.assignment.backends.sql.Assignment') def _setup_domain_test_data(self): def create_domain(domain): try: ref = self.assignment_api.create_domain( domain['id'], domain) except exception.Conflict: ref = ( self.assignment_api.get_domain_by_name(domain['name'])) return ref self.domain_default = create_domain(assignment.calc_default_domain()) self.domain1 = create_domain( {'id': uuid.uuid4().hex, 'name': 'domain1'}) self.domain2 = create_domain( {'id': uuid.uuid4().hex, 'name': 'domain2'}) self.domain3 = create_domain( {'id': uuid.uuid4().hex, 'name': 'domain3'}) self.domain4 = create_domain( {'id': uuid.uuid4().hex, 'name': 'domain4'}) def _set_domain_configs(self): # We need to load the domain configs explicitly to ensure the # test overrides are included. self.identity_api.domain_configs._load_config( self.identity_api.assignment_api, [tests.dirs.tests_conf('keystone.Default.conf')], 'Default') self.identity_api.domain_configs._load_config( self.identity_api.assignment_api, [tests.dirs.tests_conf('keystone.domain1.conf')], 'domain1') self.identity_api.domain_configs._load_config( self.identity_api.assignment_api, [tests.dirs.tests_conf('keystone.domain2.conf')], 'domain2') def reload_backends(self, domain_id): # Just reload the driver for this domain - which will pickup # any updated cfg self.identity_api.domain_configs.reload_domain_driver( self.identity_api.assignment_api, domain_id) def get_config(self, domain_id): # Get the config for this domain, will return CONF # if no specific config defined for this domain return self.identity_api.domain_configs.get_domain_conf(domain_id) def test_list_domains(self): self.skipTest( 'N/A: Not relevant for multi ldap testing') def test_list_domains_non_default_domain_id(self): self.skipTest( 'N/A: Not relevant for multi ldap testing') def test_domain_segregation(self): """Test that separate configs have segregated the domain. Test Plan: - Create a user in each of the domains - Make sure that you can only find a given user in its relevant domain - Make sure that for a backend that supports multiple domains you can get the users via any of the domain scopes """ def create_user(domain_id): user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain_id, 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user['id'], user) return user userd = create_user(CONF.identity.default_domain_id) user1 = create_user(self.domain1['id']) user2 = create_user(self.domain2['id']) user3 = create_user(self.domain3['id']) user4 = create_user(self.domain4['id']) # Now check that I can read user1 with the appropriate domain # scope, but won't find it if the wrong scope is used ref = self.identity_api.get_user( userd['id'], domain_scope=CONF.identity.default_domain_id) del userd['password'] self.assertDictEqual(ref, userd) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, userd['id'], domain_scope=self.domain1['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, userd['id'], domain_scope=self.domain2['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, userd['id'], domain_scope=self.domain3['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, userd['id'], domain_scope=self.domain4['id']) ref = self.identity_api.get_user( user1['id'], domain_scope=self.domain1['id']) del user1['password'] self.assertDictEqual(ref, user1) ref = self.identity_api.get_user( user2['id'], domain_scope=self.domain2['id']) del user2['password'] self.assertDictEqual(ref, user2) # Domains 3 and 4 share the same backend, so you should be # able to see user3 and 4 from either ref = self.identity_api.get_user( user3['id'], domain_scope=self.domain3['id']) del user3['password'] self.assertDictEqual(ref, user3) ref = self.identity_api.get_user( user4['id'], domain_scope=self.domain4['id']) del user4['password'] self.assertDictEqual(ref, user4) ref = self.identity_api.get_user( user3['id'], domain_scope=self.domain4['id']) self.assertDictEqual(ref, user3) ref = self.identity_api.get_user( user4['id'], domain_scope=self.domain3['id']) self.assertDictEqual(ref, user4) def test_scanning_of_config_dir(self): """Test the Manager class scans the config directory. The setup for the main tests above load the domain configs directly so that the test overrides can be included. This test just makes sure that the standard config directory scanning does pick up the relevant domain config files. """ # Confirm that config has drivers_enabled as True, which we will # check has been set to False later in this test self.assertTrue(config.CONF.identity.domain_specific_drivers_enabled) self.load_backends() # Execute any command to trigger the lazy loading of domain configs self.identity_api.list_users(domain_scope=self.domain1['id']) # ...and now check the domain configs have been set up self.assertIn('default', self.identity_api.domain_configs) self.assertIn(self.domain1['id'], self.identity_api.domain_configs) self.assertIn(self.domain2['id'], self.identity_api.domain_configs) self.assertNotIn(self.domain3['id'], self.identity_api.domain_configs) self.assertNotIn(self.domain4['id'], self.identity_api.domain_configs) # Finally check that a domain specific config contains items from both # the primary config and the domain specific config conf = self.identity_api.domain_configs.get_domain_conf( self.domain1['id']) # This should now be false, as is the default, since this is not # set in the standard primary config file self.assertFalse(conf.identity.domain_specific_drivers_enabled) # ..and make sure a domain-specifc options is also set self.assertEqual('fake://memory1', conf.ldap.url) def test_add_role_grant_to_user_and_project_404(self): self.skipTest('Blocked by bug 1101287') def test_get_role_grants_for_user_and_project_404(self): self.skipTest('Blocked by bug 1101287') def test_list_projects_for_user_with_grants(self): self.skipTest('Blocked by bug 1221805') keystone-2014.1/keystone/tests/test_contrib_s3_core.py0000664000175400017540000000410412323716267024301 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import uuid from keystone.contrib import s3 from keystone import exception from keystone import tests class S3ContribCore(tests.TestCase): def setUp(self): super(S3ContribCore, self).setUp() self.load_backends() self.controller = s3.S3Controller() def test_good_signature(self): creds_ref = {'secret': 'b121dd41cdcc42fe9f70e572e84295aa'} credentials = {'token': 'UFVUCjFCMk0yWThBc2dUcGdBbVk3UGhDZmc9PQphcHB' 'saWNhdGlvbi9vY3RldC1zdHJlYW0KVHVlLCAxMSBEZWMgMjAxM' 'iAyMTo0MTo0MSBHTVQKL2NvbnRfczMvdXBsb2FkZWRfZnJ' 'vbV9zMy50eHQ=', 'signature': 'IL4QLcLVaYgylF9iHj6Wb8BGZsw='} self.assertIsNone(self.controller.check_signature(creds_ref, credentials)) def test_bad_signature(self): creds_ref = {'secret': 'b121dd41cdcc42fe9f70e572e84295aa'} credentials = {'token': 'UFVUCjFCMk0yWThBc2dUcGdBbVk3UGhDZmc9PQphcHB' 'saWNhdGlvbi9vY3RldC1zdHJlYW0KVHVlLCAxMSBEZWMgMjAxM' 'iAyMTo0MTo0MSBHTVQKL2NvbnRfczMvdXBsb2FkZWRfZnJ' 'vbV9zMy50eHQ=', 'signature': uuid.uuid4().hex} self.assertRaises(exception.Unauthorized, self.controller.check_signature, creds_ref, credentials) keystone-2014.1/keystone/tests/matchers.py0000664000175400017540000000331412323716267021775 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import six from lxml import etree from testtools import matchers class XMLEquals(object): """Parses two XML documents from strings and compares the results. """ def __init__(self, expected): self.expected = expected def __str__(self): return "%s(%r)" % (self.__class__.__name__, self.expected) def match(self, other): parser = etree.XMLParser(remove_blank_text=True) def canonical_xml(s): s = s.strip() fp = six.StringIO() dom = etree.fromstring(s, parser) dom.getroottree().write_c14n(fp) s = fp.getvalue() dom = etree.fromstring(s, parser) return etree.tostring(dom, pretty_print=True) expected = canonical_xml(self.expected) other = canonical_xml(other) if expected == other: return return XMLMismatch(expected, other) class XMLMismatch(matchers.Mismatch): def __init__(self, expected, other): self.expected = expected self.other = other def describe(self): return 'expected = %s\nactual = %s' % (self.expected, self.other) keystone-2014.1/keystone/tests/test_backend_federation_sql.py0000664000175400017540000000240512323716267025674 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import sql from keystone import config from keystone.tests import test_backend_sql CONF = config.CONF class SqlFederation(test_backend_sql.SqlModels): """Set of tests for checking SQL Federation.""" def test_identity_provider(self): cols = (('id', sql.String, 64), ('enabled', sql.Boolean, None), ('description', sql.Text, None)) self.assertExpectedSchema('identity_provider', cols) def test_federated_protocol(self): cols = (('id', sql.String, 64), ('idp_id', sql.String, 64), ('mapping_id', sql.String, 64)) self.assertExpectedSchema('federation_protocol', cols) keystone-2014.1/keystone/tests/test_ipv6.py0000664000175400017540000000317212323716267022114 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import environment from keystone import config from keystone import tests from keystone.tests.ksfixtures import appserver CONF = config.CONF class IPv6TestCase(tests.TestCase): def setUp(self): self.skip_if_no_ipv6() super(IPv6TestCase, self).setUp() self.load_backends() def test_ipv6_ok(self): """Make sure both public and admin API work with ipv6.""" paste_conf = self._paste_config('keystone') # Verify Admin with appserver.AppServer(paste_conf, appserver.ADMIN, host="::1"): conn = environment.httplib.HTTPConnection('::1', CONF.admin_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) # Verify Public with appserver.AppServer(paste_conf, appserver.MAIN, host="::1"): conn = environment.httplib.HTTPConnection('::1', CONF.public_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) keystone-2014.1/keystone/tests/test_pemutils.py0000664000175400017540000002553412323716267023100 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import base64 from keystone.common import pemutils from keystone import tests from six import moves # List of 2-tuples, (pem_type, pem_header) headers = pemutils.PEM_TYPE_TO_HEADER.items() def make_data(size, offset=0): return ''.join([chr(x % 255) for x in moves.range(offset, size + offset)]) def make_base64_from_data(data): return base64.b64encode(data) def wrap_base64(base64_text): wrapped_text = '\n'.join([base64_text[x:x + 64] for x in moves.range(0, len(base64_text), 64)]) wrapped_text += '\n' return wrapped_text def make_pem(header, data): base64_text = make_base64_from_data(data) wrapped_text = wrap_base64(base64_text) result = '-----BEGIN %s-----\n' % header result += wrapped_text result += '-----END %s-----\n' % header return result class PEM(object): """PEM text and it's associated data broken out, used for testing. """ def __init__(self, pem_header='CERTIFICATE', pem_type='cert', data_size=70, data_offset=0): self.pem_header = pem_header self.pem_type = pem_type self.data_size = data_size self.data_offset = data_offset self.data = make_data(self.data_size, self.data_offset) self.base64_text = make_base64_from_data(self.data) self.wrapped_base64 = wrap_base64(self.base64_text) self.pem_text = make_pem(self.pem_header, self.data) class TestPEMParseResult(tests.TestCase): def test_pem_types(self): for pem_type in pemutils.pem_types: pem_header = pemutils.PEM_TYPE_TO_HEADER[pem_type] r = pemutils.PEMParseResult(pem_type=pem_type) self.assertEqual(pem_type, r.pem_type) self.assertEqual(pem_header, r.pem_header) pem_type = 'xxx' self.assertRaises(ValueError, pemutils.PEMParseResult, pem_type=pem_type) def test_pem_headers(self): for pem_header in pemutils.pem_headers: pem_type = pemutils.PEM_HEADER_TO_TYPE[pem_header] r = pemutils.PEMParseResult(pem_header=pem_header) self.assertEqual(pem_type, r.pem_type) self.assertEqual(pem_header, r.pem_header) pem_header = 'xxx' self.assertRaises(ValueError, pemutils.PEMParseResult, pem_header=pem_header) class TestPEMParse(tests.TestCase): def test_parse_none(self): text = '' text += 'bla bla\n' text += 'yada yada yada\n' text += 'burfl blatz bingo\n' parse_results = pemutils.parse_pem(text) self.assertEqual(len(parse_results), 0) self.assertEqual(pemutils.is_pem(text), False) def test_parse_invalid(self): p = PEM(pem_type='xxx', pem_header='XXX') text = p.pem_text self.assertRaises(ValueError, pemutils.parse_pem, text) def test_parse_one(self): data_size = 70 count = len(headers) pems = [] for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): p = pems[i] text = p.pem_text parse_results = pemutils.parse_pem(text) self.assertEqual(len(parse_results), 1) r = parse_results[0] self.assertEqual(p.pem_type, r.pem_type) self.assertEqual(p.pem_header, r.pem_header) self.assertEqual(p.pem_text, text[r.pem_start:r.pem_end]) self.assertEqual(p.wrapped_base64, text[r.base64_start:r.base64_end]) self.assertEqual(p.data, r.binary_data) def test_parse_one_embedded(self): p = PEM(data_offset=0) text = '' text += 'bla bla\n' text += 'yada yada yada\n' text += p.pem_text text += 'burfl blatz bingo\n' parse_results = pemutils.parse_pem(text) self.assertEqual(len(parse_results), 1) r = parse_results[0] self.assertEqual(p.pem_type, r.pem_type) self.assertEqual(p.pem_header, r.pem_header) self.assertEqual(p.pem_text, text[r.pem_start:r.pem_end]) self.assertEqual(p.wrapped_base64, text[r.base64_start: r.base64_end]) self.assertEqual(p.data, r.binary_data) def test_parse_multple(self): data_size = 70 count = len(headers) pems = [] text = '' for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): text += pems[i].pem_text parse_results = pemutils.parse_pem(text) self.assertEqual(len(parse_results), count) for i in moves.range(count): r = parse_results[i] p = pems[i] self.assertEqual(p.pem_type, r.pem_type) self.assertEqual(p.pem_header, r.pem_header) self.assertEqual(p.pem_text, text[r.pem_start:r.pem_end]) self.assertEqual(p.wrapped_base64, text[r.base64_start: r.base64_end]) self.assertEqual(p.data, r.binary_data) def test_parse_multple_find_specific(self): data_size = 70 count = len(headers) pems = [] text = '' for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): text += pems[i].pem_text for i in moves.range(count): parse_results = pemutils.parse_pem(text, pem_type=headers[i][0]) self.assertEqual(len(parse_results), 1) r = parse_results[0] p = pems[i] self.assertEqual(p.pem_type, r.pem_type) self.assertEqual(p.pem_header, r.pem_header) self.assertEqual(p.pem_text, text[r.pem_start:r.pem_end]) self.assertEqual(p.wrapped_base64, text[r.base64_start:r.base64_end]) self.assertEqual(p.data, r.binary_data) def test_parse_multple_embedded(self): data_size = 75 count = len(headers) pems = [] text = '' for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): text += 'bla bla\n' text += 'yada yada yada\n' text += pems[i].pem_text text += 'burfl blatz bingo\n' parse_results = pemutils.parse_pem(text) self.assertEqual(len(parse_results), count) for i in moves.range(count): r = parse_results[i] p = pems[i] self.assertEqual(p.pem_type, r.pem_type) self.assertEqual(p.pem_header, r.pem_header) self.assertEqual(p.pem_text, text[r.pem_start:r.pem_end]) self.assertEqual(p.wrapped_base64, text[r.base64_start:r.base64_end]) self.assertEqual(p.data, r.binary_data) def test_get_pem_data_none(self): text = '' text += 'bla bla\n' text += 'yada yada yada\n' text += 'burfl blatz bingo\n' data = pemutils.get_pem_data(text) self.assertIsNone(data) def test_get_pem_data_invalid(self): p = PEM(pem_type='xxx', pem_header='XXX') text = p.pem_text self.assertRaises(ValueError, pemutils.get_pem_data, text) def test_get_pem_data(self): data_size = 70 count = len(headers) pems = [] for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): p = pems[i] text = p.pem_text data = pemutils.get_pem_data(text, p.pem_type) self.assertEqual(p.data, data) def test_is_pem(self): data_size = 70 count = len(headers) pems = [] for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): p = pems[i] text = p.pem_text self.assertTrue(pemutils.is_pem(text, pem_type=p.pem_type)) self.assertFalse(pemutils.is_pem(text, pem_type=p.pem_type + 'xxx')) def test_base64_to_pem(self): data_size = 70 count = len(headers) pems = [] for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): p = pems[i] pem = pemutils.base64_to_pem(p.base64_text, p.pem_type) self.assertEqual(pemutils.get_pem_data(pem, p.pem_type), p.data) def test_binary_to_pem(self): data_size = 70 count = len(headers) pems = [] for i in moves.range(count): pems.append(PEM(pem_type=headers[i][0], pem_header=headers[i][1], data_size=data_size + i, data_offset=i)) for i in moves.range(count): p = pems[i] pem = pemutils.binary_to_pem(p.data, p.pem_type) self.assertEqual(pemutils.get_pem_data(pem, p.pem_type), p.data) keystone-2014.1/keystone/tests/config_files/0000775000175400017540000000000012323716511022233 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/config_files/deprecated_override.conf0000664000175400017540000000047612323716267027120 0ustar jenkinsjenkins00000000000000# Options in this file are deprecated. See test_config. [sql] # These options were deprecated in Icehouse with the switch to oslo's # db.sqlalchemy. connection = sqlite://deprecated idle_timeout = 54321 [database] # These are the new options from the [sql] section. connection = sqlite://new idle_timeout = 65432 keystone-2014.1/keystone/tests/config_files/backend_liveldap.conf0000664000175400017540000000063512323716267026365 0ustar jenkinsjenkins00000000000000[ldap] url = ldap://localhost user = cn=Manager,dc=openstack,dc=org password = test suffix = dc=openstack,dc=org group_tree_dn = ou=UserGroups,dc=openstack,dc=org role_tree_dn = ou=Roles,dc=openstack,dc=org tenant_tree_dn = ou=Projects,dc=openstack,dc=org user_tree_dn = ou=Users,dc=openstack,dc=org tenant_enabled_emulation = True user_enabled_emulation = True user_mail_attribute = mail use_dumb_member = True keystone-2014.1/keystone/tests/config_files/backend_multi_ldap_sql.conf0000664000175400017540000000047512323716267027600 0ustar jenkinsjenkins00000000000000[database] connection = sqlite:// #For a file based sqlite use #connection = sqlite:////tmp/keystone.db #To Test MySQL: #connection = mysql://keystone:keystone@localhost/keystone?charset=utf8 #To Test PostgreSQL: #connection = postgresql://keystone:keystone@localhost/keystone?client_encoding=utf8 idle_timeout = 200 keystone-2014.1/keystone/tests/config_files/backend_postgresql.conf0000664000175400017540000000027712323716267026772 0ustar jenkinsjenkins00000000000000#Used for running the Migrate tests against a live Postgresql Server #See _sql_livetest.py [database] connection = postgresql://keystone:keystone@localhost/keystone_test?client_encoding=utf8 keystone-2014.1/keystone/tests/config_files/keystone.domain1.conf0000664000175400017540000000037312323716267026305 0ustar jenkinsjenkins00000000000000# The domain-specific configuration file for the test domain # 'domain1' for use with unit tests. [ldap] url = fake://memory1 user = cn=Admin password = password suffix = cn=example,cn=com [identity] driver = keystone.identity.backends.ldap.Identitykeystone-2014.1/keystone/tests/config_files/backend_ldap_sql.conf0000664000175400017540000000062412323716267026362 0ustar jenkinsjenkins00000000000000[database] #For a specific location file based sqlite use: #connection = sqlite:////tmp/keystone.db #To Test MySQL: #connection = mysql://keystone:keystone@localhost/keystone?charset=utf8 #To Test PostgreSQL: #connection = postgresql://keystone:keystone@localhost/keystone?client_encoding=utf8 idle_timeout = 200 [ldap] url = fake://memory user = cn=Admin password = password suffix = cn=example,cn=com keystone-2014.1/keystone/tests/config_files/backend_tls_liveldap.conf0000664000175400017540000000102512323716267027241 0ustar jenkinsjenkins00000000000000[ldap] url = ldap:// user = dc=Manager,dc=openstack,dc=org password = test suffix = dc=openstack,dc=org group_tree_dn = ou=UserGroups,dc=openstack,dc=org role_tree_dn = ou=Roles,dc=openstack,dc=org tenant_tree_dn = ou=Projects,dc=openstack,dc=org user_tree_dn = ou=Users,dc=openstack,dc=org tenant_enabled_emulation = True user_enabled_emulation = True user_mail_attribute = mail use_dumb_member = True use_tls = True tls_cacertfile = /etc/keystone/ssl/certs/cacert.pem tls_cacertdir = /etc/keystone/ssl/certs/ tls_req_cert = demand keystone-2014.1/keystone/tests/config_files/keystone.domain2.conf0000664000175400017540000000052112323716267026301 0ustar jenkinsjenkins00000000000000# The domain-specific configuration file for the test domain # 'domain2' for use with unit tests. [ldap] url = fake://memory user = cn=Admin password = password suffix = cn=myroot,cn=com group_tree_dn = ou=UserGroups,dc=myroot,dc=org user_tree_dn = ou=Users,dc=myroot,dc=org [identity] driver = keystone.identity.backends.ldap.Identitykeystone-2014.1/keystone/tests/config_files/backend_mysql.conf0000664000175400017540000000025512323716267025730 0ustar jenkinsjenkins00000000000000#Used for running the Migrate tests against a live Mysql Server #See _sql_livetest.py [database] connection = mysql://keystone:keystone@localhost/keystone_test?charset=utf8 keystone-2014.1/keystone/tests/config_files/deprecated.conf0000664000175400017540000000031512323716267025211 0ustar jenkinsjenkins00000000000000# Options in this file are deprecated. See test_config. [sql] # These options were deprecated in Icehouse with the switch to oslo's # db.sqlalchemy. connection = sqlite://deprecated idle_timeout = 54321 keystone-2014.1/keystone/tests/config_files/backend_ldap.conf0000664000175400017540000000026212323716267025501 0ustar jenkinsjenkins00000000000000[ldap] url = fake://memory user = cn=Admin password = password backend_entities = ['Tenant', 'User', 'UserRoleAssociation', 'Role', 'Group', 'Domain'] suffix = cn=example,cn=com keystone-2014.1/keystone/tests/config_files/test_auth_plugin.conf0000664000175400017540000000022712323716267026471 0ustar jenkinsjenkins00000000000000[auth] methods = external,password,token,simple_challenge_response simple_challenge_response = keystone.tests.test_auth_plugin.SimpleChallengeResponse keystone-2014.1/keystone/tests/config_files/backend_db2.conf0000664000175400017540000000024112323716267025225 0ustar jenkinsjenkins00000000000000#Used for running the Migrate tests against a live DB2 Server #See _sql_livetest.py [database] connection = ibm_db_sa://keystone:keystone@/staktest?charset=utf8 keystone-2014.1/keystone/tests/config_files/keystone.Default.conf0000664000175400017540000000055112323716267026337 0ustar jenkinsjenkins00000000000000# The domain-specific configuration file for the default domain for # use with unit tests. # # The domain_name of the default domain is 'Default', hence the # strange mix of upper/lower case in the file name. [ldap] url = fake://memory user = cn=Admin password = password suffix = cn=example,cn=com [identity] driver = keystone.identity.backends.ldap.Identitykeystone-2014.1/keystone/tests/config_files/backend_sql.conf0000664000175400017540000000047112323716267025362 0ustar jenkinsjenkins00000000000000[database] #For a specific location file based sqlite use: #connection = sqlite:////tmp/keystone.db #To Test MySQL: #connection = mysql://keystone:keystone@localhost/keystone?charset=utf8 #To Test PostgreSQL: #connection = postgresql://keystone:keystone@localhost/keystone?client_encoding=utf8 idle_timeout = 200 keystone-2014.1/keystone/tests/test_v3_identity.py0000664000175400017540000024436412323716272023477 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import uuid from oslo.config import cfg from testtools import matchers from keystone.common import controller from keystone import exception from keystone import tests from keystone.tests import test_v3 CONF = cfg.CONF def _build_role_assignment_url_and_entity( role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False, effective=False): if user_id and domain_id: url = ('/domains/%(domain_id)s/users/%(user_id)s' '/roles/%(role_id)s' % { 'domain_id': domain_id, 'user_id': user_id, 'role_id': role_id}) entity = {'role': {'id': role_id}, 'user': {'id': user_id}, 'scope': {'domain': {'id': domain_id}}} if inherited_to_projects: url = '/OS-INHERIT%s/inherited_to_projects' % url if not effective: entity['OS-INHERIT:inherited_to'] = 'projects' elif user_id and project_id: url = ('/projects/%(project_id)s/users/%(user_id)s' '/roles/%(role_id)s' % { 'project_id': project_id, 'user_id': user_id, 'role_id': role_id}) entity = {'role': {'id': role_id}, 'user': {'id': user_id}, 'scope': {'project': {'id': project_id}}} if group_id and domain_id: url = ('/domains/%(domain_id)s/groups/%(group_id)s' '/roles/%(role_id)s' % { 'domain_id': domain_id, 'group_id': group_id, 'role_id': role_id}) entity = {'role': {'id': role_id}, 'group': {'id': group_id}, 'scope': {'domain': {'id': domain_id}}} if inherited_to_projects: url = '/OS-INHERIT%s/inherited_to_projects' % url if not effective: entity['OS-INHERIT:inherited_to'] = 'projects' elif group_id and project_id: url = ('/projects/%(project_id)s/groups/%(group_id)s' '/roles/%(role_id)s' % { 'project_id': project_id, 'group_id': group_id, 'role_id': role_id}) entity = {'role': {'id': role_id}, 'group': {'id': group_id}, 'scope': {'project': {'id': project_id}}} return (url, entity) class IdentityTestCase(test_v3.RestfulTestCase): """Test domains, projects, users, groups, & role CRUD.""" def setUp(self): super(IdentityTestCase, self).setUp() self.group_id = uuid.uuid4().hex self.group = self.new_group_ref( domain_id=self.domain_id) self.group['id'] = self.group_id self.identity_api.create_group(self.group_id, self.group) self.credential_id = uuid.uuid4().hex self.credential = self.new_credential_ref( user_id=self.user['id'], project_id=self.project_id) self.credential['id'] = self.credential_id self.credential_api.create_credential( self.credential_id, self.credential) # domain crud tests def test_create_domain(self): """Call ``POST /domains``.""" ref = self.new_domain_ref() r = self.post( '/domains', body={'domain': ref}) return self.assertValidDomainResponse(r, ref) def test_create_domain_case_sensitivity(self): """Call `POST /domains`` twice with upper() and lower() cased name.""" ref = self.new_domain_ref() # ensure the name is lowercase ref['name'] = ref['name'].lower() r = self.post( '/domains', body={'domain': ref}) self.assertValidDomainResponse(r, ref) # ensure the name is uppercase ref['name'] = ref['name'].upper() r = self.post( '/domains', body={'domain': ref}) self.assertValidDomainResponse(r, ref) def test_create_domain_400(self): """Call ``POST /domains``.""" self.post('/domains', body={'domain': {}}, expected_status=400) def test_list_domains(self): """Call ``GET /domains``.""" r = self.get('/domains') self.assertValidDomainListResponse(r, ref=self.domain) def test_list_domains_xml(self): """Call ``GET /domains (xml data)``.""" r = self.get('/domains', content_type='xml') self.assertValidDomainListResponse(r, ref=self.domain) def test_get_domain(self): """Call ``GET /domains/{domain_id}``.""" r = self.get('/domains/%(domain_id)s' % { 'domain_id': self.domain_id}) self.assertValidDomainResponse(r, self.domain) def test_update_domain(self): """Call ``PATCH /domains/{domain_id}``.""" ref = self.new_domain_ref() del ref['id'] r = self.patch('/domains/%(domain_id)s' % { 'domain_id': self.domain_id}, body={'domain': ref}) self.assertValidDomainResponse(r, ref) def test_disable_domain(self): """Call ``PATCH /domains/{domain_id}`` (set enabled=False).""" # Create a 2nd set of entities in a 2nd domain self.domain2 = self.new_domain_ref() self.assignment_api.create_domain(self.domain2['id'], self.domain2) self.project2 = self.new_project_ref( domain_id=self.domain2['id']) self.assignment_api.create_project(self.project2['id'], self.project2) self.user2 = self.new_user_ref( domain_id=self.domain2['id'], project_id=self.project2['id']) self.identity_api.create_user(self.user2['id'], self.user2) self.assignment_api.add_user_to_project(self.project2['id'], self.user2['id']) # First check a user in that domain can authenticate, via # Both v2 and v3 body = { 'auth': { 'passwordCredentials': { 'userId': self.user2['id'], 'password': self.user2['password'] }, 'tenantId': self.project2['id'] } } self.admin_request(path='/v2.0/tokens', method='POST', body=body) auth_data = self.build_authentication_request( user_id=self.user2['id'], password=self.user2['password'], project_id=self.project2['id']) self.post('/auth/tokens', body=auth_data) # Now disable the domain self.domain2['enabled'] = False r = self.patch('/domains/%(domain_id)s' % { 'domain_id': self.domain2['id']}, body={'domain': {'enabled': False}}) self.assertValidDomainResponse(r, self.domain2) # Make sure the user can no longer authenticate, via # either API body = { 'auth': { 'passwordCredentials': { 'userId': self.user2['id'], 'password': self.user2['password'] }, 'tenantId': self.project2['id'] } } self.admin_request( path='/v2.0/tokens', method='POST', body=body, expected_status=401) # Try looking up in v3 by name and id auth_data = self.build_authentication_request( user_id=self.user2['id'], password=self.user2['password'], project_id=self.project2['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) auth_data = self.build_authentication_request( username=self.user2['name'], user_domain_id=self.domain2['id'], password=self.user2['password'], project_id=self.project2['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_delete_enabled_domain_fails(self): """Call ``DELETE /domains/{domain_id}`` (when domain enabled).""" # Try deleting an enabled domain, which should fail self.delete('/domains/%(domain_id)s' % { 'domain_id': self.domain['id']}, expected_status=exception.ForbiddenAction.code) def test_delete_domain(self): """Call ``DELETE /domains/{domain_id}``. The sample data set up already has a user, group, project and credential that is part of self.domain. Since the user we will authenticate with is in this domain, we create a another set of entities in a second domain. Deleting this second domain should delete all these new entities. In addition, all the entities in the regular self.domain should be unaffected by the delete. Test Plan: - Create domain2 and a 2nd set of entities - Disable domain2 - Delete domain2 - Check entities in domain2 have been deleted - Check entities in self.domain are unaffected """ # Create a 2nd set of entities in a 2nd domain self.domain2 = self.new_domain_ref() self.assignment_api.create_domain(self.domain2['id'], self.domain2) self.project2 = self.new_project_ref( domain_id=self.domain2['id']) self.assignment_api.create_project(self.project2['id'], self.project2) self.user2 = self.new_user_ref( domain_id=self.domain2['id'], project_id=self.project2['id']) self.identity_api.create_user(self.user2['id'], self.user2) self.group2 = self.new_group_ref( domain_id=self.domain2['id']) self.identity_api.create_group(self.group2['id'], self.group2) self.credential2 = self.new_credential_ref( user_id=self.user2['id'], project_id=self.project2['id']) self.credential_api.create_credential( self.credential2['id'], self.credential2) # Now disable the new domain and delete it self.domain2['enabled'] = False r = self.patch('/domains/%(domain_id)s' % { 'domain_id': self.domain2['id']}, body={'domain': {'enabled': False}}) self.assertValidDomainResponse(r, self.domain2) self.delete('/domains/%(domain_id)s' % { 'domain_id': self.domain2['id']}) # Check all the domain2 relevant entities are gone self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, self.domain2['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, self.project2['id']) self.assertRaises(exception.GroupNotFound, self.identity_api.get_group, self.group2['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, self.user2['id']) self.assertRaises(exception.CredentialNotFound, self.credential_api.get_credential, self.credential2['id']) # ...and that all self.domain entities are still here r = self.assignment_api.get_domain(self.domain['id']) self.assertDictEqual(r, self.domain) r = self.assignment_api.get_project(self.project['id']) self.assertDictEqual(r, self.project) r = self.identity_api.get_group(self.group['id']) self.assertDictEqual(r, self.group) r = self.identity_api.get_user(self.user['id']) self.user.pop('password') self.assertDictEqual(r, self.user) r = self.credential_api.get_credential(self.credential['id']) self.assertDictEqual(r, self.credential) def test_delete_default_domain_fails(self): # Attempting to delete the default domain results in 403 Forbidden. # Need to disable it first. self.patch('/domains/%(domain_id)s' % { 'domain_id': CONF.identity.default_domain_id}, body={'domain': {'enabled': False}}) self.delete('/domains/%(domain_id)s' % { 'domain_id': CONF.identity.default_domain_id}, expected_status=exception.ForbiddenAction.code) def test_delete_new_default_domain_fails(self): # If change the default domain ID, deleting the new default domain # results in a 403 Forbidden. # Create a new domain that's not the default new_domain = self.new_domain_ref() new_domain_id = new_domain['id'] self.assignment_api.create_domain(new_domain_id, new_domain) # Disable the new domain so can delete it later. self.patch('/domains/%(domain_id)s' % { 'domain_id': new_domain_id}, body={'domain': {'enabled': False}}) # Change the default domain self.config_fixture.config(group='identity', default_domain_id=new_domain_id) # Attempt to delete the new domain self.delete('/domains/%(domain_id)s' % {'domain_id': new_domain_id}, expected_status=exception.ForbiddenAction.code) def test_delete_old_default_domain(self): # If change the default domain ID, deleting the old default domain # works. # Create a new domain that's not the default new_domain = self.new_domain_ref() new_domain_id = new_domain['id'] self.assignment_api.create_domain(new_domain_id, new_domain) old_default_domain_id = CONF.identity.default_domain_id # Disable the default domain so we can delete it later. self.patch('/domains/%(domain_id)s' % { 'domain_id': old_default_domain_id}, body={'domain': {'enabled': False}}) # Change the default domain self.config_fixture.config(group='identity', default_domain_id=new_domain_id) # Delete the old default domain self.delete( '/domains/%(domain_id)s' % {'domain_id': old_default_domain_id}) # project crud tests def test_list_projects(self): """Call ``GET /projects``.""" r = self.get('/projects') self.assertValidProjectListResponse(r, ref=self.project) def test_list_projects_xml(self): """Call ``GET /projects`` (xml data).""" r = self.get('/projects', content_type='xml') self.assertValidProjectListResponse(r, ref=self.project) def test_create_project(self): """Call ``POST /projects``.""" ref = self.new_project_ref(domain_id=self.domain_id) r = self.post( '/projects', body={'project': ref}) self.assertValidProjectResponse(r, ref) def test_create_project_400(self): """Call ``POST /projects``.""" self.post('/projects', body={'project': {}}, expected_status=400) def test_get_project(self): """Call ``GET /projects/{project_id}``.""" r = self.get( '/projects/%(project_id)s' % { 'project_id': self.project_id}) self.assertValidProjectResponse(r, self.project) def test_update_project(self): """Call ``PATCH /projects/{project_id}``.""" ref = self.new_project_ref(domain_id=self.domain_id) del ref['id'] r = self.patch( '/projects/%(project_id)s' % { 'project_id': self.project_id}, body={'project': ref}) self.assertValidProjectResponse(r, ref) def test_update_project_domain_id(self): """Call ``PATCH /projects/{project_id}`` with domain_id.""" project = self.new_project_ref(domain_id=self.domain['id']) self.assignment_api.create_project(project['id'], project) project['domain_id'] = CONF.identity.default_domain_id r = self.patch('/projects/%(project_id)s' % { 'project_id': project['id']}, body={'project': project}, expected_status=exception.ValidationError.code) self.config_fixture.config(domain_id_immutable=False) project['domain_id'] = self.domain['id'] r = self.patch('/projects/%(project_id)s' % { 'project_id': project['id']}, body={'project': project}) self.assertValidProjectResponse(r, project) def test_delete_project(self): """Call ``DELETE /projects/{project_id}`` As well as making sure the delete succeeds, we ensure that any credentials that reference this projects are also deleted, while other credentials are unaffected. """ # First check the credential for this project is present r = self.credential_api.get_credential(self.credential['id']) self.assertDictEqual(r, self.credential) # Create a second credential with a different project self.project2 = self.new_project_ref( domain_id=self.domain['id']) self.assignment_api.create_project(self.project2['id'], self.project2) self.credential2 = self.new_credential_ref( user_id=self.user['id'], project_id=self.project2['id']) self.credential_api.create_credential( self.credential2['id'], self.credential2) # Now delete the project self.delete( '/projects/%(project_id)s' % { 'project_id': self.project_id}) # Deleting the project should have deleted any credentials # that reference this project self.assertRaises(exception.CredentialNotFound, self.credential_api.get_credential, credential_id=self.credential['id']) # But the credential for project2 is unaffected r = self.credential_api.get_credential(self.credential2['id']) self.assertDictEqual(r, self.credential2) # user crud tests def test_create_user(self): """Call ``POST /users``.""" ref = self.new_user_ref(domain_id=self.domain_id) r = self.post( '/users', body={'user': ref}) return self.assertValidUserResponse(r, ref) def test_create_user_400(self): """Call ``POST /users``.""" self.post('/users', body={'user': {}}, expected_status=400) def test_list_users(self): """Call ``GET /users``.""" r = self.get('/users') self.assertValidUserListResponse(r, ref=self.user) def test_list_users_no_default_project(self): """Call ``GET /users`` making sure no default_project_id.""" user = self.new_user_ref(self.domain_id) self.identity_api.create_user(self.user_id, user) r = self.get('/users') self.assertValidUserListResponse(r, ref=user) def test_list_users_xml(self): """Call ``GET /users`` (xml data).""" r = self.get('/users', content_type='xml') self.assertValidUserListResponse(r, ref=self.user) def test_get_user(self): """Call ``GET /users/{user_id}``.""" r = self.get('/users/%(user_id)s' % { 'user_id': self.user['id']}) self.assertValidUserResponse(r, self.user) def test_get_user_with_default_project(self): """Call ``GET /users/{user_id}`` making sure of default_project_id.""" user = self.new_user_ref(domain_id=self.domain_id, project_id=self.project_id) self.identity_api.create_user(self.user_id, user) r = self.get('/users/%(user_id)s' % {'user_id': user['id']}) self.assertValidUserResponse(r, user) def test_add_user_to_group(self): """Call ``PUT /groups/{group_id}/users/{user_id}``.""" self.put('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user['id']}) def test_list_groups_for_user(self): """Call ``GET /users/{user_id}/groups``.""" self.user1 = self.new_user_ref( domain_id=self.domain['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref( domain_id=self.domain['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user2) self.put('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user1['id']}) #Scenarios below are written to test the default policy configuration #One should be allowed to list one's own groups auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password']) r = self.get('/users/%(user_id)s/groups' % { 'user_id': self.user1['id']}, auth=auth) self.assertValidGroupListResponse(r, ref=self.group) #Administrator is allowed to list others' groups r = self.get('/users/%(user_id)s/groups' % { 'user_id': self.user1['id']}) self.assertValidGroupListResponse(r, ref=self.group) #Ordinary users should not be allowed to list other's groups auth = self.build_authentication_request( user_id=self.user2['id'], password=self.user2['password']) r = self.get('/users/%(user_id)s/groups' % { 'user_id': self.user1['id']}, auth=auth, expected_status=exception.ForbiddenAction.code) def test_check_user_in_group(self): """Call ``HEAD /groups/{group_id}/users/{user_id}``.""" self.put('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user['id']}) self.head('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user['id']}) def test_list_users_in_group(self): """Call ``GET /groups/{group_id}/users``.""" self.put('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user['id']}) r = self.get('/groups/%(group_id)s/users' % { 'group_id': self.group_id}) self.assertValidUserListResponse(r, ref=self.user) self.assertIn('/groups/%(group_id)s/users' % { 'group_id': self.group_id}, r.result['links']['self']) def test_remove_user_from_group(self): """Call ``DELETE /groups/{group_id}/users/{user_id}``.""" self.put('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user['id']}) self.delete('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group_id, 'user_id': self.user['id']}) def test_update_user(self): """Call ``PATCH /users/{user_id}``.""" user = self.new_user_ref(domain_id=self.domain_id) del user['id'] r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body={'user': user}) self.assertValidUserResponse(r, user) def test_update_user_domain_id(self): """Call ``PATCH /users/{user_id}`` with domain_id.""" user = self.new_user_ref(domain_id=self.domain['id']) self.identity_api.create_user(user['id'], user) user['domain_id'] = CONF.identity.default_domain_id r = self.patch('/users/%(user_id)s' % { 'user_id': user['id']}, body={'user': user}, expected_status=exception.ValidationError.code) self.config_fixture.config(domain_id_immutable=False) user['domain_id'] = self.domain['id'] r = self.patch('/users/%(user_id)s' % { 'user_id': user['id']}, body={'user': user}) self.assertValidUserResponse(r, user) def test_delete_user(self): """Call ``DELETE /users/{user_id}``. As well as making sure the delete succeeds, we ensure that any credentials that reference this user are also deleted, while other credentials are unaffected. In addition, no tokens should remain valid for this user. """ # First check the credential for this user is present r = self.credential_api.get_credential(self.credential['id']) self.assertDictEqual(r, self.credential) # Create a second credential with a different user self.user2 = self.new_user_ref( domain_id=self.domain['id'], project_id=self.project['id']) self.identity_api.create_user(self.user2['id'], self.user2) self.credential2 = self.new_credential_ref( user_id=self.user2['id'], project_id=self.project['id']) self.credential_api.create_credential( self.credential2['id'], self.credential2) # Create a token for this user which we can check later # gets deleted auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # Confirm token is valid for now self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) # Now delete the user self.delete('/users/%(user_id)s' % { 'user_id': self.user['id']}) # Deleting the user should have deleted any credentials # that reference this project self.assertRaises(exception.CredentialNotFound, self.credential_api.get_credential, self.credential['id']) # And the no tokens we remain valid tokens = self.token_api._list_tokens(self.user['id']) self.assertEqual(0, len(tokens)) # But the credential for user2 is unaffected r = self.credential_api.get_credential(self.credential2['id']) self.assertDictEqual(r, self.credential2) # group crud tests def test_create_group(self): """Call ``POST /groups``.""" ref = self.new_group_ref(domain_id=self.domain_id) r = self.post( '/groups', body={'group': ref}) return self.assertValidGroupResponse(r, ref) def test_create_group_400(self): """Call ``POST /groups``.""" self.post('/groups', body={'group': {}}, expected_status=400) def test_list_groups(self): """Call ``GET /groups``.""" r = self.get('/groups') self.assertValidGroupListResponse(r, ref=self.group) def test_list_groups_xml(self): """Call ``GET /groups`` (xml data).""" r = self.get('/groups', content_type='xml') self.assertValidGroupListResponse(r, ref=self.group) def test_get_group(self): """Call ``GET /groups/{group_id}``.""" r = self.get('/groups/%(group_id)s' % { 'group_id': self.group_id}) self.assertValidGroupResponse(r, self.group) def test_update_group(self): """Call ``PATCH /groups/{group_id}``.""" group = self.new_group_ref(domain_id=self.domain_id) del group['id'] r = self.patch('/groups/%(group_id)s' % { 'group_id': self.group_id}, body={'group': group}) self.assertValidGroupResponse(r, group) def test_update_group_domain_id(self): """Call ``PATCH /groups/{group_id}`` with domain_id.""" group = self.new_group_ref(domain_id=self.domain['id']) self.identity_api.create_group(group['id'], group) group['domain_id'] = CONF.identity.default_domain_id r = self.patch('/groups/%(group_id)s' % { 'group_id': group['id']}, body={'group': group}, expected_status=exception.ValidationError.code) self.config_fixture.config(domain_id_immutable=False) group['domain_id'] = self.domain['id'] r = self.patch('/groups/%(group_id)s' % { 'group_id': group['id']}, body={'group': group}) self.assertValidGroupResponse(r, group) def test_delete_group(self): """Call ``DELETE /groups/{group_id}``.""" self.delete('/groups/%(group_id)s' % { 'group_id': self.group_id}) # role crud tests def test_create_role(self): """Call ``POST /roles``.""" ref = self.new_role_ref() r = self.post( '/roles', body={'role': ref}) return self.assertValidRoleResponse(r, ref) def test_create_role_400(self): """Call ``POST /roles``.""" self.post('/roles', body={'role': {}}, expected_status=400) def test_list_roles(self): """Call ``GET /roles``.""" r = self.get('/roles') self.assertValidRoleListResponse(r, ref=self.role) def test_list_roles_xml(self): """Call ``GET /roles`` (xml data).""" r = self.get('/roles', content_type='xml') self.assertValidRoleListResponse(r, ref=self.role) def test_get_role(self): """Call ``GET /roles/{role_id}``.""" r = self.get('/roles/%(role_id)s' % { 'role_id': self.role_id}) self.assertValidRoleResponse(r, self.role) def test_update_role(self): """Call ``PATCH /roles/{role_id}``.""" ref = self.new_role_ref() del ref['id'] r = self.patch('/roles/%(role_id)s' % { 'role_id': self.role_id}, body={'role': ref}) self.assertValidRoleResponse(r, ref) def test_delete_role(self): """Call ``DELETE /roles/{role_id}``.""" self.delete('/roles/%(role_id)s' % { 'role_id': self.role_id}) def test_crud_user_project_role_grants(self): collection_url = ( '/projects/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': self.project['id'], 'user_id': self.user['id']}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=self.role) self.assertIn(collection_url, r.result['links']['self']) # FIXME(gyee): this test is no longer valid as user # have no role in the project. Can't get a scoped token #self.delete(member_url) #r = self.get(collection_url) #self.assertValidRoleListResponse(r, expected_length=0) #self.assertIn(collection_url, r.result['links']['self']) def test_crud_user_project_role_grants_no_user(self): """Grant role on a project to a user that doesn't exist, 404 result. When grant a role on a project to a user that doesn't exist, the server returns 404 Not Found for the user. """ user_id = uuid.uuid4().hex collection_url = ( '/projects/%(project_id)s/users/%(user_id)s/roles' % { 'project_id': self.project['id'], 'user_id': user_id}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url, expected_status=404) def test_crud_user_domain_role_grants(self): collection_url = ( '/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': self.domain_id, 'user_id': self.user['id']}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=self.role) self.assertIn(collection_url, r.result['links']['self']) self.delete(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, expected_length=0) self.assertIn(collection_url, r.result['links']['self']) def test_crud_user_domain_role_grants_no_user(self): """Grant role on a domain to a user that doesn't exist, 404 result. When grant a role on a domain to a user that doesn't exist, the server returns 404 Not Found for the user. """ user_id = uuid.uuid4().hex collection_url = ( '/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': self.domain_id, 'user_id': user_id}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url, expected_status=404) def test_crud_group_project_role_grants(self): collection_url = ( '/projects/%(project_id)s/groups/%(group_id)s/roles' % { 'project_id': self.project_id, 'group_id': self.group_id}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=self.role) self.assertIn(collection_url, r.result['links']['self']) self.delete(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, expected_length=0) self.assertIn(collection_url, r.result['links']['self']) def test_crud_group_project_role_grants_no_group(self): """Grant role on a project to a group that doesn't exist, 404 result. When grant a role on a project to a group that doesn't exist, the server returns 404 Not Found for the group. """ group_id = uuid.uuid4().hex collection_url = ( '/projects/%(project_id)s/groups/%(group_id)s/roles' % { 'project_id': self.project_id, 'group_id': group_id}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url, expected_status=404) def test_crud_group_domain_role_grants(self): collection_url = ( '/domains/%(domain_id)s/groups/%(group_id)s/roles' % { 'domain_id': self.domain_id, 'group_id': self.group_id}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=self.role) self.assertIn(collection_url, r.result['links']['self']) self.delete(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, expected_length=0) self.assertIn(collection_url, r.result['links']['self']) def test_crud_group_domain_role_grants_no_group(self): """Grant role on a domain to a group that doesn't exist, 404 result. When grant a role on a domain to a group that doesn't exist, the server returns 404 Not Found for the group. """ group_id = uuid.uuid4().hex collection_url = ( '/domains/%(domain_id)s/groups/%(group_id)s/roles' % { 'domain_id': self.domain_id, 'group_id': group_id}) member_url = '%(collection_url)s/%(role_id)s' % { 'collection_url': collection_url, 'role_id': self.role_id} self.put(member_url, expected_status=404) def test_get_role_assignments(self): """Call ``GET /role_assignments``. The sample data set up already has a user, group and project that is part of self.domain. We use these plus a new user we create as our data set, making sure we ignore any role assignments that are already in existence. Since we don't yet support a first class entity for role assignments, we are only testing the LIST API. To create and delete the role assignments we use the old grant APIs. Test Plan: - Create extra user for tests - Get a list of all existing role assignments - Add a new assignment for each of the four combinations, i.e. group+domain, user+domain, group+project, user+project, using the same role each time - Get a new list of all role assignments, checking these four new ones have been added - Then delete the four we added - Get a new list of all role assignments, checking the four have been removed """ # Since the default fixtures already assign some roles to the # user it creates, we also need a new user that will not have any # existing assignments self.user1 = self.new_user_ref( domain_id=self.domain['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) collection_url = '/role_assignments' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertIn(collection_url, r.result['links']['self']) existing_assignments = len(r.result.get('role_assignments')) # Now add one of each of the four types of assignment, making sure # that we get them all back. gd_url, gd_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, group_id=self.group_id, role_id=self.role_id) self.put(gd_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 1, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) ud_url, ud_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, user_id=self.user1['id'], role_id=self.role_id) self.put(ud_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 2, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url) gp_url, gp_entity = _build_role_assignment_url_and_entity( project_id=self.project_id, group_id=self.group_id, role_id=self.role_id) self.put(gp_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 3, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url) up_url, up_entity = _build_role_assignment_url_and_entity( project_id=self.project_id, user_id=self.user1['id'], role_id=self.role_id) self.put(up_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 4, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url) # Now delete the four we added and make sure they are removed # from the collection. self.delete(gd_url) self.delete(ud_url) self.delete(gp_url) self.delete(up_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments, len(r.result.get('role_assignments'))) self.assertRoleAssignmentNotInListResponse(r, gd_entity) self.assertRoleAssignmentNotInListResponse(r, ud_entity) self.assertRoleAssignmentNotInListResponse(r, gp_entity) self.assertRoleAssignmentNotInListResponse(r, up_entity) def test_get_effective_role_assignments(self): """Call ``GET /role_assignments?effective``. Test Plan: - Create two extra user for tests - Add these users to a group - Add a role assignment for the group on a domain - Get a list of all role assignments, checking one has been added - Then get a list of all effective role assignments - the group assignment should have turned into assignments on the domain for each of the group members. """ self.user1 = self.new_user_ref( domain_id=self.domain['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref( domain_id=self.domain['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user2['id'], self.user2) self.identity_api.add_user_to_group(self.user1['id'], self.group['id']) self.identity_api.add_user_to_group(self.user2['id'], self.group['id']) collection_url = '/role_assignments' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertIn(collection_url, r.result['links']['self']) existing_assignments = len(r.result.get('role_assignments')) gd_url, gd_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, group_id=self.group_id, role_id=self.role_id) self.put(gd_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 1, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) # Now re-read the collection asking for effective roles - this # should mean the group assignment is translated into the two # member user assignments collection_url = '/role_assignments?effective' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 2, len(r.result.get('role_assignments'))) unused, ud_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, user_id=self.user1['id'], role_id=self.role_id) gd_url, unused = _build_role_assignment_url_and_entity( domain_id=self.domain_id, group_id=self.group['id'], role_id=self.role_id) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=gd_url) ud_url, ud_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, user_id=self.user2['id'], role_id=self.role_id) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=gd_url) def test_check_effective_values_for_role_assignments(self): """Call ``GET /role_assignments?effective=value``. Check the various ways of specifying the 'effective' query parameter. If the 'effective' query parameter is included then this should always be treated as as meaning 'True' unless it is specified as: {url}?effective=0 This is by design to match the agreed way of handling policy checking on query/filter parameters. Test Plan: - Create two extra user for tests - Add these users to a group - Add a role assignment for the group on a domain - Get a list of all role assignments, checking one has been added - Then issue various request with different ways of defining the 'effective' query parameter. As we have tested the correctness of the data coming back when we get effective roles in other tests, here we just use the count of entities to know if we are getting effective roles or not """ self.user1 = self.new_user_ref( domain_id=self.domain['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref( domain_id=self.domain['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user2['id'], self.user2) self.identity_api.add_user_to_group(self.user1['id'], self.group['id']) self.identity_api.add_user_to_group(self.user2['id'], self.group['id']) collection_url = '/role_assignments' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) existing_assignments = len(r.result.get('role_assignments')) gd_url, gd_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, group_id=self.group_id, role_id=self.role_id) self.put(gd_url) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 1, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) # Now re-read the collection asking for effective roles, # using the most common way of defining "effective'. This # should mean the group assignment is translated into the two # member user assignments collection_url = '/role_assignments?effective' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 2, len(r.result.get('role_assignments'))) # Now set 'effective' to false explicitly - should get # back the regular roles collection_url = '/role_assignments?effective=0' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 1, len(r.result.get('role_assignments'))) # Now try setting 'effective' to 'False' explicitly- this is # NOT supported as a way of setting a query or filter # parameter to false by design. Hence we should get back # effective roles. collection_url = '/role_assignments?effective=False' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 2, len(r.result.get('role_assignments'))) # Now set 'effective' to True explicitly collection_url = '/role_assignments?effective=True' r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(existing_assignments + 2, len(r.result.get('role_assignments'))) def test_filtered_role_assignments(self): """Call ``GET /role_assignments?filters``. Test Plan: - Create extra users, group, role and project for tests - Make the following assignments: Give group1, role1 on project1 and domain Give user1, role2 on project1 and domain Make User1 a member of Group1 - Test a series of single filter list calls, checking that the correct results are obtained - Test a multi-filtered list call - Test listing all effective roles for a given user - Test the equivalent of the list of roles in a project scoped token (all effective roles for a user on a project) """ # Since the default fixtures already assign some roles to the # user it creates, we also need a new user that will not have any # existing assignments self.user1 = self.new_user_ref( domain_id=self.domain['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref( domain_id=self.domain['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user2['id'], self.user2) self.group1 = self.new_group_ref( domain_id=self.domain['id']) self.identity_api.create_group(self.group1['id'], self.group1) self.identity_api.add_user_to_group(self.user1['id'], self.group1['id']) self.identity_api.add_user_to_group(self.user2['id'], self.group1['id']) self.project1 = self.new_project_ref( domain_id=self.domain['id']) self.assignment_api.create_project(self.project1['id'], self.project1) self.role1 = self.new_role_ref() self.assignment_api.create_role(self.role1['id'], self.role1) self.role2 = self.new_role_ref() self.assignment_api.create_role(self.role2['id'], self.role2) # Now add one of each of the four types of assignment gd_url, gd_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, group_id=self.group1['id'], role_id=self.role1['id']) self.put(gd_url) ud_url, ud_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, user_id=self.user1['id'], role_id=self.role2['id']) self.put(ud_url) gp_url, gp_entity = _build_role_assignment_url_and_entity( project_id=self.project1['id'], group_id=self.group1['id'], role_id=self.role1['id']) self.put(gp_url) up_url, up_entity = _build_role_assignment_url_and_entity( project_id=self.project1['id'], user_id=self.user1['id'], role_id=self.role2['id']) self.put(up_url) # Now list by various filters to make sure we get back the right ones collection_url = ('/role_assignments?scope.project.id=%s' % self.project1['id']) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url) self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url) collection_url = ('/role_assignments?scope.domain.id=%s' % self.domain['id']) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) collection_url = '/role_assignments?user.id=%s' % self.user1['id'] r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url) collection_url = '/role_assignments?group.id=%s' % self.group1['id'] r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url) collection_url = '/role_assignments?role.id=%s' % self.role1['id'] r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) self.assertRoleAssignmentInListResponse(r, gp_entity, link_url=gp_url) # Let's try combining two filers together.... collection_url = ( '/role_assignments?user.id=%(user_id)s' '&scope.project.id=%(project_id)s' % { 'user_id': self.user1['id'], 'project_id': self.project1['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(1, len(r.result.get('role_assignments'))) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url) # Now for a harder one - filter for user with effective # roles - this should return role assignment that were directly # assigned as well as by virtue of group membership collection_url = ('/role_assignments?effective&user.id=%s' % self.user1['id']) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(4, len(r.result.get('role_assignments'))) # Should have the two direct roles... self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url) # ...and the two via group membership... unused, up1_entity = _build_role_assignment_url_and_entity( project_id=self.project1['id'], user_id=self.user1['id'], role_id=self.role1['id']) unused, ud1_entity = _build_role_assignment_url_and_entity( domain_id=self.domain_id, user_id=self.user1['id'], role_id=self.role1['id']) gp1_url, unused = _build_role_assignment_url_and_entity( project_id=self.project1['id'], group_id=self.group1['id'], role_id=self.role1['id']) gd1_url, unused = _build_role_assignment_url_and_entity( domain_id=self.domain_id, group_id=self.group1['id'], role_id=self.role1['id']) self.assertRoleAssignmentInListResponse(r, up1_entity, link_url=gp1_url) self.assertRoleAssignmentInListResponse(r, ud1_entity, link_url=gd1_url) # ...and for the grand-daddy of them all, simulate the request # that would generate the list of effective roles in a project # scoped token. collection_url = ( '/role_assignments?effective&user.id=%(user_id)s' '&scope.project.id=%(project_id)s' % { 'user_id': self.user1['id'], 'project_id': self.project1['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) # Should have one direct role and one from group membership... self.assertRoleAssignmentInListResponse(r, up_entity, link_url=up_url) self.assertRoleAssignmentInListResponse(r, up1_entity, link_url=gp1_url) class IdentityInheritanceTestCase(test_v3.RestfulTestCase): """Test inheritance crud and its effects.""" def config_overrides(self): super(IdentityInheritanceTestCase, self).config_overrides() self.config_fixture.config(group='os_inherit', enabled=True) def test_crud_user_inherited_domain_role_grants(self): role_list = [] for _ in range(2): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) # Create a non-inherited role as a spoiler self.assignment_api.create_grant( role_list[1]['id'], user_id=self.user['id'], domain_id=self.domain_id) base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': self.domain_id, 'user_id': self.user['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role_list[0]['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url) # Check we can read it back self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=role_list[0]) self.assertIn(collection_url, r.result['links']['self']) # Now delete and check its gone self.delete(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, expected_length=0) self.assertIn(collection_url, r.result['links']['self']) def test_list_role_assignments_for_inherited_domain_grants(self): """Call ``GET /role_assignments with inherited domain grants``. Test Plan: - Create 4 roles - Create a domain with a user and two projects - Assign two direct roles to project1 - Assign a spoiler role to project2 - Issue the URL to add inherited role to the domain - Issue the URL to check it is indeed on the domain - Issue the URL to check effective roles on project1 - this should return 3 roles. """ role_list = [] for _ in range(4): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain = self.new_domain_ref() self.assignment_api.create_domain(domain['id'], domain) user1 = self.new_user_ref( domain_id=domain['id']) user1['password'] = uuid.uuid4().hex self.identity_api.create_user(user1['id'], user1) project1 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project1['id'], project1) project2 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project2['id'], project2) # Add some roles to the project self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[0]['id']) self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[1]['id']) # ..and one on a different project as a spoiler self.assignment_api.add_role_to_user_and_project( user1['id'], project2['id'], role_list[2]['id']) # Now create our inherited role on the domain base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': domain['id'], 'user_id': user1['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role_list[3]['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=role_list[3]) self.assertIn(collection_url, r.result['links']['self']) # Now use the list domain role assignments api to check if this # is included collection_url = ( '/role_assignments?user.id=%(user_id)s' '&scope.domain.id=%(domain_id)s' % { 'user_id': user1['id'], 'domain_id': domain['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(1, len(r.result.get('role_assignments'))) ud_url, ud_entity = _build_role_assignment_url_and_entity( domain_id=domain['id'], user_id=user1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url) # Now ask for effective list role assignments - the role should # turn into a project role, along with the two direct roles that are # on the project collection_url = ( '/role_assignments?effective&user.id=%(user_id)s' '&scope.project.id=%(project_id)s' % { 'user_id': user1['id'], 'project_id': project1['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(3, len(r.result.get('role_assignments'))) # An effective role for an inherited role will be a project # entity, with a domain link to the inherited assignment unused, up_entity = _build_role_assignment_url_and_entity( project_id=project1['id'], user_id=user1['id'], role_id=role_list[3]['id']) ud_url, unused = _build_role_assignment_url_and_entity( domain_id=domain['id'], user_id=user1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=ud_url) def test_list_role_assignments_for_disabled_inheritance_extension(self): """Call ``GET /role_assignments with inherited domain grants``. Test Plan: - Issue the URL to add inherited role to the domain - Issue the URL to check effective roles on project include the inherited role - Disable the extension - Re-check the effective roles, proving the inherited role no longer shows up. """ role_list = [] for _ in range(4): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain = self.new_domain_ref() self.assignment_api.create_domain(domain['id'], domain) user1 = self.new_user_ref( domain_id=domain['id']) user1['password'] = uuid.uuid4().hex self.identity_api.create_user(user1['id'], user1) project1 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project1['id'], project1) project2 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project2['id'], project2) # Add some roles to the project self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[0]['id']) self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[1]['id']) # ..and one on a different project as a spoiler self.assignment_api.add_role_to_user_and_project( user1['id'], project2['id'], role_list[2]['id']) # Now create our inherited role on the domain base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': domain['id'], 'user_id': user1['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role_list[3]['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=role_list[3]) self.assertIn(collection_url, r.result['links']['self']) # Get effective list role assignments - the role should # turn into a project role, along with the two direct roles that are # on the project collection_url = ( '/role_assignments?effective&user.id=%(user_id)s' '&scope.project.id=%(project_id)s' % { 'user_id': user1['id'], 'project_id': project1['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(3, len(r.result.get('role_assignments'))) unused, up_entity = _build_role_assignment_url_and_entity( project_id=project1['id'], user_id=user1['id'], role_id=role_list[3]['id']) ud_url, unused = _build_role_assignment_url_and_entity( domain_id=domain['id'], user_id=user1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=ud_url) # Disable the extension and re-check the list, the role inherited # from the project should no longer show up self.config_fixture.config(group='os_inherit', enabled=False) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) unused, up_entity = _build_role_assignment_url_and_entity( project_id=project1['id'], user_id=user1['id'], role_id=role_list[3]['id']) ud_url, unused = _build_role_assignment_url_and_entity( domain_id=domain['id'], user_id=user1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) self.assertRoleAssignmentNotInListResponse(r, up_entity, link_url=ud_url) def test_list_role_assignments_for_inherited_group_domain_grants(self): """Call ``GET /role_assignments with inherited group domain grants``. Test Plan: - Create 4 roles - Create a domain with a user and two projects - Assign two direct roles to project1 - Assign a spoiler role to project2 - Issue the URL to add inherited role to the domain - Issue the URL to check it is indeed on the domain - Issue the URL to check effective roles on project1 - this should return 3 roles. """ role_list = [] for _ in range(4): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain = self.new_domain_ref() self.assignment_api.create_domain(domain['id'], domain) user1 = self.new_user_ref( domain_id=domain['id']) user1['password'] = uuid.uuid4().hex self.identity_api.create_user(user1['id'], user1) user2 = self.new_user_ref( domain_id=domain['id']) user2['password'] = uuid.uuid4().hex self.identity_api.create_user(user2['id'], user2) group1 = self.new_group_ref( domain_id=domain['id']) self.identity_api.create_group(group1['id'], group1) self.identity_api.add_user_to_group(user1['id'], group1['id']) self.identity_api.add_user_to_group(user2['id'], group1['id']) project1 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project1['id'], project1) project2 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project2['id'], project2) # Add some roles to the project self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[0]['id']) self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[1]['id']) # ..and one on a different project as a spoiler self.assignment_api.add_role_to_user_and_project( user1['id'], project2['id'], role_list[2]['id']) # Now create our inherited role on the domain base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/groups/%(group_id)s/roles' % { 'domain_id': domain['id'], 'group_id': group1['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role_list[3]['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=role_list[3]) self.assertIn(collection_url, r.result['links']['self']) # Now use the list domain role assignments api to check if this # is included collection_url = ( '/role_assignments?group.id=%(group_id)s' '&scope.domain.id=%(domain_id)s' % { 'group_id': group1['id'], 'domain_id': domain['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(1, len(r.result.get('role_assignments'))) gd_url, gd_entity = _build_role_assignment_url_and_entity( domain_id=domain['id'], group_id=group1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) # Now ask for effective list role assignments - the role should # turn into a user project role, along with the two direct roles # that are on the project collection_url = ( '/role_assignments?effective&user.id=%(user_id)s' '&scope.project.id=%(project_id)s' % { 'user_id': user1['id'], 'project_id': project1['id']}) r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(3, len(r.result.get('role_assignments'))) # An effective role for an inherited role will be a project # entity, with a domain link to the inherited assignment unused, up_entity = _build_role_assignment_url_and_entity( project_id=project1['id'], user_id=user1['id'], role_id=role_list[3]['id']) gd_url, unused = _build_role_assignment_url_and_entity( domain_id=domain['id'], group_id=group1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) self.assertRoleAssignmentInListResponse(r, up_entity, link_url=gd_url) def test_filtered_role_assignments_for_inherited_grants(self): """Call ``GET /role_assignments?scope.OS-INHERIT:inherited_to``. Test Plan: - Create 5 roles - Create a domain with a user, group and two projects - Assign three direct spoiler roles to projects - Issue the URL to add an inherited user role to the domain - Issue the URL to add an inherited group role to the domain - Issue the URL to filter by inherited roles - this should return just the 2 inherited roles. """ role_list = [] for _ in range(5): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain = self.new_domain_ref() self.assignment_api.create_domain(domain['id'], domain) user1 = self.new_user_ref( domain_id=domain['id']) user1['password'] = uuid.uuid4().hex self.identity_api.create_user(user1['id'], user1) group1 = self.new_group_ref( domain_id=domain['id']) self.identity_api.create_group(group1['id'], group1) project1 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project1['id'], project1) project2 = self.new_project_ref( domain_id=domain['id']) self.assignment_api.create_project(project2['id'], project2) # Add some spoiler roles to the projects self.assignment_api.add_role_to_user_and_project( user1['id'], project1['id'], role_list[0]['id']) self.assignment_api.add_role_to_user_and_project( user1['id'], project2['id'], role_list[1]['id']) # Create a non-inherited role as a spoiler self.assignment_api.create_grant( role_list[2]['id'], user_id=user1['id'], domain_id=domain['id']) # Now create two inherited roles on the domain, one for a user # and one for a domain base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': domain['id'], 'user_id': user1['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role_list[3]['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=role_list[3]) self.assertIn(collection_url, r.result['links']['self']) base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/groups/%(group_id)s/roles' % { 'domain_id': domain['id'], 'group_id': group1['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role_list[4]['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url) self.head(member_url) r = self.get(collection_url) self.assertValidRoleListResponse(r, ref=role_list[4]) self.assertIn(collection_url, r.result['links']['self']) # Now use the list role assignments api to get a list of inherited # roles on the domain - should get back the two roles collection_url = ( '/role_assignments?scope.OS-INHERIT:inherited_to=projects') r = self.get(collection_url) self.assertValidRoleAssignmentListResponse(r) self.assertEqual(2, len(r.result.get('role_assignments'))) ud_url, ud_entity = _build_role_assignment_url_and_entity( domain_id=domain['id'], user_id=user1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) gd_url, gd_entity = _build_role_assignment_url_and_entity( domain_id=domain['id'], group_id=group1['id'], role_id=role_list[4]['id'], inherited_to_projects=True) self.assertRoleAssignmentInListResponse(r, ud_entity, link_url=ud_url) self.assertRoleAssignmentInListResponse(r, gd_entity, link_url=gd_url) class IdentityInheritanceDisabledTestCase(test_v3.RestfulTestCase): """Test inheritance crud and its effects.""" def config_overrides(self): super(IdentityInheritanceDisabledTestCase, self).config_overrides() self.config_fixture.config(group='os_inherit', enabled=False) def test_crud_inherited_role_grants_failed_if_disabled(self): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) base_collection_url = ( '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % { 'domain_id': self.domain_id, 'user_id': self.user['id']}) member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % { 'collection_url': base_collection_url, 'role_id': role['id']} collection_url = base_collection_url + '/inherited_to_projects' self.put(member_url, expected_status=404) self.head(member_url, expected_status=404) self.get(collection_url, expected_status=404) self.delete(member_url, expected_status=404) class TestV3toV2Methods(tests.TestCase): """Test V3 to V2 conversion methods.""" def setUp(self): super(TestV3toV2Methods, self).setUp() self.load_backends() self.user_id = uuid.uuid4().hex self.default_project_id = uuid.uuid4().hex self.tenant_id = uuid.uuid4().hex self.domain_id = uuid.uuid4().hex # User with only default_project_id in ref self.user1 = {'id': self.user_id, 'name': self.user_id, 'default_project_id': self.default_project_id, 'domain_id': self.domain_id} # User without default_project_id or tenantId in ref self.user2 = {'id': self.user_id, 'name': self.user_id, 'domain_id': self.domain_id} # User with both tenantId and default_project_id in ref self.user3 = {'id': self.user_id, 'name': self.user_id, 'default_project_id': self.default_project_id, 'tenantId': self.tenant_id, 'domain_id': self.domain_id} # User with only tenantId in ref self.user4 = {'id': self.user_id, 'name': self.user_id, 'tenantId': self.tenant_id, 'domain_id': self.domain_id} # Expected result if the user is meant to have a tenantId element self.expected_user = {'id': self.user_id, 'name': self.user_id, 'username': self.user_id, 'tenantId': self.default_project_id} # Expected result if the user is not meant ot have a tenantId element self.expected_user_no_tenant_id = {'id': self.user_id, 'name': self.user_id, 'username': self.user_id} def test_v3_to_v2_user_method(self): updated_user1 = controller.V2Controller.v3_to_v2_user(self.user1) self.assertIs(self.user1, updated_user1) self.assertDictEqual(self.user1, self.expected_user) updated_user2 = controller.V2Controller.v3_to_v2_user(self.user2) self.assertIs(self.user2, updated_user2) self.assertDictEqual(self.user2, self.expected_user_no_tenant_id) updated_user3 = controller.V2Controller.v3_to_v2_user(self.user3) self.assertIs(self.user3, updated_user3) self.assertDictEqual(self.user3, self.expected_user) updated_user4 = controller.V2Controller.v3_to_v2_user(self.user4) self.assertIs(self.user4, updated_user4) self.assertDictEqual(self.user4, self.expected_user_no_tenant_id) def test_v3_to_v2_user_method_list(self): user_list = [self.user1, self.user2, self.user3, self.user4] updated_list = controller.V2Controller.v3_to_v2_user(user_list) self.assertEqual(len(updated_list), len(user_list)) for i, ref in enumerate(updated_list): # Order should not change. self.assertIs(ref, user_list[i]) self.assertDictEqual(self.user1, self.expected_user) self.assertDictEqual(self.user2, self.expected_user_no_tenant_id) self.assertDictEqual(self.user3, self.expected_user) self.assertDictEqual(self.user4, self.expected_user_no_tenant_id) def test_v2controller_filter_domain_id(self): # V2.0 is not domain aware, ensure domain_id is popped off the ref. other_data = uuid.uuid4().hex domain_id = uuid.uuid4().hex ref = {'domain_id': domain_id, 'other_data': other_data} ref_no_domain = {'other_data': other_data} expected_ref = ref_no_domain.copy() updated_ref = controller.V2Controller.filter_domain_id(ref) self.assertIs(ref, updated_ref) self.assertDictEqual(ref, expected_ref) # Make sure we don't error/muck up data if domain_id isn't present updated_ref = controller.V2Controller.filter_domain_id(ref_no_domain) self.assertIs(ref_no_domain, updated_ref) self.assertDictEqual(ref_no_domain, expected_ref) def test_v3controller_filter_domain_id(self): # No data should be filtered out in this case. other_data = uuid.uuid4().hex domain_id = uuid.uuid4().hex ref = {'domain_id': domain_id, 'other_data': other_data} expected_ref = ref.copy() updated_ref = controller.V3Controller.filter_domain_id(ref) self.assertIs(ref, updated_ref) self.assertDictEqual(ref, expected_ref) class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase): def setUp(self): super(UserSelfServiceChangingPasswordsTestCase, self).setUp() self.user_ref = self.new_user_ref(domain_id=self.domain['id']) self.identity_api.create_user(self.user_ref['id'], self.user_ref) self.token = self.get_request_token(self.user_ref['password'], 201) def get_request_token(self, password, expected_status): auth_data = self.build_authentication_request( user_id=self.user_ref['id'], password=password) r = self.post('/auth/tokens', body=auth_data, expected_status=expected_status) return r.headers.get('X-Subject-Token') def change_password(self, expected_status, **kwargs): """Returns a test response for a change password request.""" return self.post('/users/%s/password' % self.user_ref['id'], body={'user': kwargs}, token=self.token, expected_status=expected_status) def test_changing_password(self): # original password works self.get_request_token(self.user_ref['password'], expected_status=201) # change password new_password = uuid.uuid4().hex self.change_password(password=new_password, original_password=self.user_ref['password'], expected_status=204) # old password fails self.get_request_token(self.user_ref['password'], expected_status=401) # new password works self.get_request_token(new_password, expected_status=201) def test_changing_password_with_missing_original_password_fails(self): r = self.change_password(password=uuid.uuid4().hex, expected_status=400) self.assertThat(r.result['error']['message'], matchers.Contains('original_password')) def test_changing_password_with_missing_password_fails(self): r = self.change_password(original_password=self.user_ref['password'], expected_status=400) self.assertThat(r.result['error']['message'], matchers.Contains('password')) def test_changing_password_with_incorrect_password_fails(self): self.change_password(password=uuid.uuid4().hex, original_password=uuid.uuid4().hex, expected_status=401) def test_changing_password_with_disabled_user_fails(self): # disable the user account self.user_ref['enabled'] = False self.patch('/users/%s' % self.user_ref['id'], body={'user': self.user_ref}) self.change_password(password=uuid.uuid4().hex, original_password=self.user_ref['password'], expected_status=401) keystone-2014.1/keystone/tests/test_v3_catalog.py0000664000175400017540000003702712323716272023254 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import copy import uuid from keystone.tests import test_v3 class CatalogTestCase(test_v3.RestfulTestCase): """Test service & endpoint CRUD.""" # region crud tests def test_create_region_with_id(self): """Call ``PUT /regions/{region_id}`` w/o an ID in the request body.""" ref = self.new_region_ref() region_id = ref.pop('id') r = self.put( '/regions/%s' % region_id, body={'region': ref}, expected_status=201) self.assertValidRegionResponse(r, ref) # Double-check that the region ID was kept as-is and not # populated with a UUID, as is the case with POST /v3/regions self.assertEqual(region_id, r.json['region']['id']) def test_create_region_with_matching_ids(self): """Call ``PUT /regions/{region_id}`` with an ID in the request body.""" ref = self.new_region_ref() region_id = ref['id'] r = self.put( '/regions/%s' % region_id, body={'region': ref}, expected_status=201) self.assertValidRegionResponse(r, ref) # Double-check that the region ID was kept as-is and not # populated with a UUID, as is the case with POST /v3/regions self.assertEqual(region_id, r.json['region']['id']) def test_create_region_with_duplicate_id(self): """Call ``PUT /regions/{region_id}``.""" ref = dict(description="my region") self.put( '/regions/myregion', body={'region': ref}, expected_status=201) # Create region again with duplicate id self.put( '/regions/myregion', body={'region': ref}, expected_status=409) def test_create_region(self): """Call ``POST /regions`` with an ID in the request body.""" # the ref will have an ID defined on it ref = self.new_region_ref() r = self.post( '/regions', body={'region': ref}) self.assertValidRegionResponse(r, ref) # we should be able to get the region, having defined the ID ourselves r = self.get( '/regions/%(region_id)s' % { 'region_id': ref['id']}) self.assertValidRegionResponse(r, ref) def test_create_region_without_id(self): """Call ``POST /regions`` without an ID in the request body.""" ref = self.new_region_ref() # instead of defining the ID ourselves... del ref['id'] # let the service define the ID r = self.post( '/regions', body={'region': ref}, expected_status=201) self.assertValidRegionResponse(r, ref) def test_create_region_with_conflicting_ids(self): """Call ``PUT /regions/{region_id}`` with conflicting region IDs.""" # the region ref is created with an ID ref = self.new_region_ref() # but instead of using that ID, make up a new, conflicting one self.put( '/regions/%s' % uuid.uuid4().hex, body={'region': ref}, expected_status=400) def test_list_regions(self): """Call ``GET /regions``.""" r = self.get('/regions') self.assertValidRegionListResponse(r, ref=self.region) def test_list_regions_xml(self): """Call ``GET /regions (xml data)``.""" r = self.get('/regions', content_type='xml') self.assertValidRegionListResponse(r, ref=self.region) def test_get_region(self): """Call ``GET /regions/{region_id}``.""" r = self.get('/regions/%(region_id)s' % { 'region_id': self.region_id}) self.assertValidRegionResponse(r, self.region) def test_update_region(self): """Call ``PATCH /regions/{region_id}``.""" region = self.new_region_ref() del region['id'] r = self.patch('/regions/%(region_id)s' % { 'region_id': self.region_id}, body={'region': region}) self.assertValidRegionResponse(r, region) def test_delete_region(self): """Call ``DELETE /regions/{region_id}``.""" self.delete('/regions/%(region_id)s' % { 'region_id': self.region_id}) # service crud tests def test_create_service(self): """Call ``POST /services``.""" ref = self.new_service_ref() r = self.post( '/services', body={'service': ref}) self.assertValidServiceResponse(r, ref) def test_create_service_no_enabled(self): """Call ``POST /services``.""" ref = self.new_service_ref() del ref['enabled'] r = self.post( '/services', body={'service': ref}) ref['enabled'] = True self.assertValidServiceResponse(r, ref) self.assertIs(True, r.result['service']['enabled']) def test_create_service_enabled_false(self): """Call ``POST /services``.""" ref = self.new_service_ref() ref['enabled'] = False r = self.post( '/services', body={'service': ref}) self.assertValidServiceResponse(r, ref) self.assertIs(False, r.result['service']['enabled']) def test_create_service_enabled_true(self): """Call ``POST /services``.""" ref = self.new_service_ref() ref['enabled'] = True r = self.post( '/services', body={'service': ref}) self.assertValidServiceResponse(r, ref) self.assertIs(True, r.result['service']['enabled']) def test_create_service_enabled_str_true(self): """Call ``POST /services``.""" ref = self.new_service_ref() ref['enabled'] = 'True' self.post('/services', body={'service': ref}, expected_status=400) def test_create_service_enabled_str_false(self): """Call ``POST /services``.""" ref = self.new_service_ref() ref['enabled'] = 'False' self.post('/services', body={'service': ref}, expected_status=400) def test_create_service_enabled_str_random(self): """Call ``POST /services``.""" ref = self.new_service_ref() ref['enabled'] = 'puppies' self.post('/services', body={'service': ref}, expected_status=400) def test_list_services(self): """Call ``GET /services``.""" r = self.get('/services') self.assertValidServiceListResponse(r, ref=self.service) def test_list_services_xml(self): """Call ``GET /services (xml data)``.""" r = self.get('/services', content_type='xml') self.assertValidServiceListResponse(r, ref=self.service) def test_get_service(self): """Call ``GET /services/{service_id}``.""" r = self.get('/services/%(service_id)s' % { 'service_id': self.service_id}) self.assertValidServiceResponse(r, self.service) def test_update_service(self): """Call ``PATCH /services/{service_id}``.""" service = self.new_service_ref() del service['id'] r = self.patch('/services/%(service_id)s' % { 'service_id': self.service_id}, body={'service': service}) self.assertValidServiceResponse(r, service) def test_delete_service(self): """Call ``DELETE /services/{service_id}``.""" self.delete('/services/%(service_id)s' % { 'service_id': self.service_id}) # endpoint crud tests def test_list_endpoints(self): """Call ``GET /endpoints``.""" r = self.get('/endpoints') self.assertValidEndpointListResponse(r, ref=self.endpoint) def test_list_endpoints_xml(self): """Call ``GET /endpoints`` (xml data).""" r = self.get('/endpoints', content_type='xml') self.assertValidEndpointListResponse(r, ref=self.endpoint) def test_create_endpoint_no_enabled(self): """Call ``POST /endpoints``.""" ref = self.new_endpoint_ref(service_id=self.service_id) r = self.post( '/endpoints', body={'endpoint': ref}) ref['enabled'] = True self.assertValidEndpointResponse(r, ref) def test_create_endpoint_enabled_true(self): """Call ``POST /endpoints`` with enabled: true.""" ref = self.new_endpoint_ref(service_id=self.service_id, enabled=True) r = self.post( '/endpoints', body={'endpoint': ref}) self.assertValidEndpointResponse(r, ref) def test_create_endpoint_enabled_false(self): """Call ``POST /endpoints`` with enabled: false.""" ref = self.new_endpoint_ref(service_id=self.service_id, enabled=False) r = self.post( '/endpoints', body={'endpoint': ref}) self.assertValidEndpointResponse(r, ref) def test_create_endpoint_enabled_str_true(self): """Call ``POST /endpoints`` with enabled: 'True'.""" ref = self.new_endpoint_ref(service_id=self.service_id, enabled='True') self.post( '/endpoints', body={'endpoint': ref}, expected_status=400) def test_create_endpoint_enabled_str_false(self): """Call ``POST /endpoints`` with enabled: 'False'.""" ref = self.new_endpoint_ref(service_id=self.service_id, enabled='False') self.post( '/endpoints', body={'endpoint': ref}, expected_status=400) def test_create_endpoint_enabled_str_random(self): """Call ``POST /endpoints`` with enabled: 'puppies'.""" ref = self.new_endpoint_ref(service_id=self.service_id, enabled='puppies') self.post( '/endpoints', body={'endpoint': ref}, expected_status=400) def assertValidErrorResponse(self, response): self.assertTrue(response.status_code in [400, 409]) def test_create_endpoint_400(self): """Call ``POST /endpoints``.""" ref = self.new_endpoint_ref(service_id=self.service_id) ref["region"] = "0" * 256 self.post('/endpoints', body={'endpoint': ref}, expected_status=400) def test_create_endpoint_with_empty_url(self): """Call ``POST /endpoints``.""" ref = self.new_endpoint_ref(service_id=self.service_id) del ref["url"] self.post('/endpoints', body={'endpoint': ref}, expected_status=400) def test_get_endpoint(self): """Call ``GET /endpoints/{endpoint_id}``.""" r = self.get( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}) self.assertValidEndpointResponse(r, self.endpoint) def test_update_endpoint(self): """Call ``PATCH /endpoints/{endpoint_id}``.""" ref = self.new_endpoint_ref(service_id=self.service_id) del ref['id'] r = self.patch( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}, body={'endpoint': ref}) ref['enabled'] = True self.assertValidEndpointResponse(r, ref) def test_update_endpoint_enabled_true(self): """Call ``PATCH /endpoints/{endpoint_id}`` with enabled: True.""" r = self.patch( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}, body={'endpoint': {'enabled': True}}) self.assertValidEndpointResponse(r, self.endpoint) def test_update_endpoint_enabled_false(self): """Call ``PATCH /endpoints/{endpoint_id}`` with enabled: False.""" r = self.patch( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}, body={'endpoint': {'enabled': False}}) exp_endpoint = copy.copy(self.endpoint) exp_endpoint['enabled'] = False self.assertValidEndpointResponse(r, exp_endpoint) def test_update_endpoint_enabled_str_true(self): """Call ``PATCH /endpoints/{endpoint_id}`` with enabled: 'True'.""" self.patch( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}, body={'endpoint': {'enabled': 'True'}}, expected_status=400) def test_update_endpoint_enabled_str_false(self): """Call ``PATCH /endpoints/{endpoint_id}`` with enabled: 'False'.""" self.patch( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}, body={'endpoint': {'enabled': 'False'}}, expected_status=400) def test_update_endpoint_enabled_str_random(self): """Call ``PATCH /endpoints/{endpoint_id}`` with enabled: 'kitties'.""" self.patch( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}, body={'endpoint': {'enabled': 'kitties'}}, expected_status=400) def test_delete_endpoint(self): """Call ``DELETE /endpoints/{endpoint_id}``.""" self.delete( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}) def test_create_endpoint_on_v2(self): # clear the v3 endpoint so we only have endpoints created on v2 self.delete( '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}) # create a v3 endpoint ref, and then tweak it back to a v2-style ref ref = self.new_endpoint_ref(service_id=self.service['id']) del ref['id'] del ref['interface'] ref['publicurl'] = ref.pop('url') ref['internalurl'] = None # don't set adminurl to ensure it's absence is handled like internalurl # create the endpoint on v2 (using a v3 token) r = self.admin_request( method='POST', path='/v2.0/endpoints', token=self.get_scoped_token(), body={'endpoint': ref}) endpoint_v2 = r.result['endpoint'] # test the endpoint on v3 r = self.get('/endpoints') endpoints = self.assertValidEndpointListResponse(r) self.assertEqual(len(endpoints), 1) endpoint_v3 = endpoints.pop() # these attributes are identical between both API's self.assertEqual(endpoint_v3['region'], ref['region']) self.assertEqual(endpoint_v3['service_id'], ref['service_id']) self.assertEqual(endpoint_v3['description'], ref['description']) # a v2 endpoint is not quite the same concept as a v3 endpoint, so they # receive different identifiers self.assertNotEqual(endpoint_v2['id'], endpoint_v3['id']) # v2 has a publicurl; v3 has a url + interface type self.assertEqual(endpoint_v3['url'], ref['publicurl']) self.assertEqual(endpoint_v3['interface'], 'public') # tests for bug 1152632 -- these attributes were being returned by v3 self.assertNotIn('publicurl', endpoint_v3) self.assertNotIn('adminurl', endpoint_v3) self.assertNotIn('internalurl', endpoint_v3) # test for bug 1152635 -- this attribute was being returned by v3 self.assertNotIn('legacy_endpoint_id', endpoint_v3) keystone-2014.1/keystone/tests/test_cache_backend_mongo.py0000664000175400017540000006563312323716272025147 0ustar jenkinsjenkins00000000000000# Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import collections import copy import functools import uuid from dogpile.cache import api from dogpile.cache import region as dp_region import six import testtools from keystone.common.cache.backends import mongo from keystone import exception # Mock database structure sample where 'ks_cache' is database and # 'cache' is collection. Dogpile CachedValue data is divided in two # fields `value` (CachedValue.payload) and `meta` (CachedValue.metadata) ks_cache = { "cache": [ { "value": { "serviceType": "identity", "allVersionsUrl": "https://dummyUrl", "dateLastModified": "ISODDate(2014-02-08T18:39:13.237Z)", "serviceName": "Identity", "enabled": "True" }, "meta": { "v": 1, "ct": 1392371422.015121 }, "doc_date": "ISODate('2014-02-14T09:50:22.015Z')", "_id": "8251dc95f63842719c077072f1047ddf" }, { "value": "dummyValueX", "meta": { "v": 1, "ct": 1392371422.014058 }, "doc_date": "ISODate('2014-02-14T09:50:22.014Z')", "_id": "66730b9534d146f0804d23729ad35436" } ] } COLLECTIONS = {} SON_MANIPULATOR = None class MockCursor(object): def __init__(self, collection, dataset_factory): super(MockCursor, self).__init__() self.collection = collection self._factory = dataset_factory self._dataset = self._factory() self._limit = None self._skip = None def __iter__(self): return self def __next__(self): if self._skip: for _ in range(self._skip): next(self._dataset) self._skip = None if self._limit is not None and self._limit <= 0: raise StopIteration() if self._limit is not None: self._limit -= 1 return next(self._dataset) next = __next__ def __getitem__(self, index): arr = [x for x in self._dataset] self._dataset = iter(arr) return arr[index] class MockCollection(object): def __init__(self, db, name): super(MockCollection, self).__init__() self.name = name self._collection_database = db self._documents = {} self.write_concern = {} def __getattr__(self, name): if name == 'database': return self._collection_database def ensure_index(self, key_or_list, *args, **kwargs): pass def index_information(self): return {} def find_one(self, spec_or_id=None, *args, **kwargs): if spec_or_id is None: spec_or_id = {} if not isinstance(spec_or_id, collections.Mapping): spec_or_id = {'_id': spec_or_id} try: return next(self.find(spec_or_id, *args, **kwargs)) except StopIteration: return None def find(self, spec=None, *args, **kwargs): return MockCursor(self, functools.partial(self._get_dataset, spec)) def _get_dataset(self, spec): dataset = (self._copy_doc(document, dict) for document in self._iter_documents(spec)) return dataset def _iter_documents(self, spec=None): return (SON_MANIPULATOR.transform_outgoing(document, self) for document in six.itervalues(self._documents) if self._apply_filter(document, spec)) def _apply_filter(self, document, query): for key, search in query.iteritems(): doc_val = document.get(key) if isinstance(search, dict): op_dict = {'$in': lambda dv, sv: dv in sv} is_match = all( op_str in op_dict and op_dict[op_str](doc_val, search_val) for op_str, search_val in six.iteritems(search) ) else: is_match = doc_val == search return is_match def _copy_doc(self, obj, container): if isinstance(obj, list): new = [] for item in obj: new.append(self._copy_doc(item, container)) return new if isinstance(obj, dict): new = container() for key, value in obj.items(): new[key] = self._copy_doc(value, container) return new else: return copy.copy(obj) def insert(self, data, manipulate=True, **kwargs): if isinstance(data, list): return [self._insert(element) for element in data] return self._insert(data) def save(self, data, manipulate=True, **kwargs): return self._insert(data) def _insert(self, data): if '_id' not in data: data['_id'] = uuid.uuid4().hex object_id = data['_id'] self._documents[object_id] = self._internalize_dict(data) return object_id def find_and_modify(self, spec, document, upsert=False, **kwargs): self.update(spec, document, upsert, **kwargs) def update(self, spec, document, upsert=False, **kwargs): existing_docs = [doc for doc in six.itervalues(self._documents) if self._apply_filter(doc, spec)] if existing_docs: existing_doc = existing_docs[0] # should find only 1 match _id = existing_doc['_id'] existing_doc.clear() existing_doc['_id'] = _id existing_doc.update(self._internalize_dict(document)) elif upsert: existing_doc = self._documents[self._insert(document)] def _internalize_dict(self, d): return dict((k, copy.deepcopy(v)) for k, v in six.iteritems(d)) def remove(self, spec_or_id=None, search_filter=None): """Remove objects matching spec_or_id from the collection.""" if spec_or_id is None: spec_or_id = search_filter if search_filter else {} if not isinstance(spec_or_id, dict): spec_or_id = {'_id': spec_or_id} to_delete = list(self.find(spec=spec_or_id)) for doc in to_delete: doc_id = doc['_id'] del self._documents[doc_id] return { "connectionId": uuid.uuid4().hex, "n": len(to_delete), "ok": 1.0, "err": None, } class MockMongoDB(object): def __init__(self, dbname): self._dbname = dbname self.mainpulator = None def authenticate(self, username, password): pass def add_son_manipulator(self, manipulator): global SON_MANIPULATOR SON_MANIPULATOR = manipulator def __getattr__(self, name): if name == 'authenticate': return self.authenticate elif name == 'name': return self._dbname elif name == 'add_son_manipulator': return self.add_son_manipulator else: return get_collection(self._dbname, name) def __getitem__(self, name): return get_collection(self._dbname, name) class MockMongoClient(object): def __init__(self, *args, **kwargs): pass def __getattr__(self, dbname): return MockMongoDB(dbname) def get_collection(db_name, collection_name): mongo_collection = MockCollection(MockMongoDB(db_name), collection_name) return mongo_collection def pymongo_override(): global pymongo import pymongo if pymongo.MongoClient is not MockMongoClient: pymongo.MongoClient = MockMongoClient if pymongo.MongoReplicaSetClient is not MockMongoClient: pymongo.MongoClient = MockMongoClient class MyTransformer(mongo.BaseTransform): """Added here just to check manipulator logic is used correctly.""" def transform_incoming(self, son, collection): return super(MyTransformer, self).transform_incoming(son, collection) def transform_outgoing(self, son, collection): return super(MyTransformer, self).transform_outgoing(son, collection) class MongoCache(testtools.TestCase): def setUp(self): super(MongoCache, self).setUp() global COLLECTIONS COLLECTIONS = {} mongo.MongoApi._DB = {} mongo.MongoApi._MONGO_COLLS = {} pymongo_override() # using typical configuration self.arguments = { 'db_hosts': 'localhost:27017', 'db_name': 'ks_cache', 'cache_collection': 'cache', 'username': 'test_user', 'password': 'test_password' } def test_missing_db_hosts(self): self.arguments.pop('db_hosts') region = dp_region.make_region() self.assertRaises(exception.ValidationError, region.configure, 'keystone.cache.mongo', arguments=self.arguments) def test_missing_db_name(self): self.arguments.pop('db_name') region = dp_region.make_region() self.assertRaises(exception.ValidationError, region.configure, 'keystone.cache.mongo', arguments=self.arguments) def test_missing_cache_collection_name(self): self.arguments.pop('cache_collection') region = dp_region.make_region() self.assertRaises(exception.ValidationError, region.configure, 'keystone.cache.mongo', arguments=self.arguments) def test_incorrect_write_concern(self): self.arguments['w'] = 'one value' region = dp_region.make_region() self.assertRaises(exception.ValidationError, region.configure, 'keystone.cache.mongo', arguments=self.arguments) def test_correct_write_concern(self): self.arguments['w'] = 1 region = dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue10") # There is no proxy so can access MongoCacheBackend directly self.assertEqual(region.backend.api.w, 1) def test_incorrect_read_preference(self): self.arguments['read_preference'] = 'inValidValue' region = dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) # As per delayed loading of pymongo, read_preference value should # still be string and NOT enum self.assertEqual(region.backend.api.read_preference, 'inValidValue') random_key = uuid.uuid4().hex self.assertRaises(ValueError, region.set, random_key, "dummyValue10") def test_correct_read_preference(self): self.arguments['read_preference'] = 'secondaryPreferred' region = dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) # As per delayed loading of pymongo, read_preference value should # still be string and NOT enum self.assertEqual(region.backend.api.read_preference, 'secondaryPreferred') random_key = uuid.uuid4().hex region.set(random_key, "dummyValue10") # Now as pymongo is loaded so expected read_preference value is enum. # There is no proxy so can access MongoCacheBackend directly self.assertEqual(region.backend.api.read_preference, 3) def test_missing_replica_set_name(self): self.arguments['use_replica'] = True region = dp_region.make_region() self.assertRaises(exception.ValidationError, region.configure, 'keystone.cache.mongo', arguments=self.arguments) def test_provided_replica_set_name(self): self.arguments['use_replica'] = True self.arguments['replicaset_name'] = 'my_replica' dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) self.assertTrue(True) # reached here means no initialization error def test_incorrect_mongo_ttl_seconds(self): self.arguments['mongo_ttl_seconds'] = 'sixty' region = dp_region.make_region() self.assertRaises(exception.ValidationError, region.configure, 'keystone.cache.mongo', arguments=self.arguments) def test_cache_configuration_values_assertion(self): self.arguments['use_replica'] = True self.arguments['replicaset_name'] = 'my_replica' self.arguments['mongo_ttl_seconds'] = 60 self.arguments['ssl'] = False region = dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) # There is no proxy so can access MongoCacheBackend directly self.assertEqual(region.backend.api.hosts, 'localhost:27017') self.assertEqual(region.backend.api.db_name, 'ks_cache') self.assertEqual(region.backend.api.cache_collection, 'cache') self.assertEqual(region.backend.api.username, 'test_user') self.assertEqual(region.backend.api.password, 'test_password') self.assertEqual(region.backend.api.use_replica, True) self.assertEqual(region.backend.api.replicaset_name, 'my_replica') self.assertEqual(region.backend.api.conn_kwargs['ssl'], False) self.assertEqual(region.backend.api.ttl_seconds, 60) def test_multiple_region_cache_configuration(self): arguments1 = copy.copy(self.arguments) arguments1['cache_collection'] = 'cache_region1' region1 = dp_region.make_region().configure('keystone.cache.mongo', arguments=arguments1) # There is no proxy so can access MongoCacheBackend directly self.assertEqual(region1.backend.api.hosts, 'localhost:27017') self.assertEqual(region1.backend.api.db_name, 'ks_cache') self.assertEqual(region1.backend.api.cache_collection, 'cache_region1') self.assertEqual(region1.backend.api.username, 'test_user') self.assertEqual(region1.backend.api.password, 'test_password') # Should be None because of delayed initialization self.assertIsNone(region1.backend.api._data_manipulator) random_key1 = uuid.uuid4().hex region1.set(random_key1, "dummyValue10") self.assertEqual("dummyValue10", region1.get(random_key1)) # Now should have initialized self.assertIsInstance(region1.backend.api._data_manipulator, mongo.BaseTransform) class_name = '%s.%s' % (MyTransformer.__module__, "MyTransformer") arguments2 = copy.copy(self.arguments) arguments2['cache_collection'] = 'cache_region2' arguments2['son_manipulator'] = class_name region2 = dp_region.make_region().configure('keystone.cache.mongo', arguments=arguments2) # There is no proxy so can access MongoCacheBackend directly self.assertEqual(region2.backend.api.hosts, 'localhost:27017') self.assertEqual(region2.backend.api.db_name, 'ks_cache') self.assertEqual(region2.backend.api.cache_collection, 'cache_region2') # Should be None because of delayed initialization self.assertIsNone(region2.backend.api._data_manipulator) random_key = uuid.uuid4().hex region2.set(random_key, "dummyValue20") self.assertEqual("dummyValue20", region2.get(random_key)) # Now should have initialized self.assertIsInstance(region2.backend.api._data_manipulator, MyTransformer) region1.set(random_key1, "dummyValue22") self.assertEqual("dummyValue22", region1.get(random_key1)) def test_typical_configuration(self): dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) self.assertTrue(True) # reached here means no initialization error def test_backend_get_missing_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, region.get(random_key)) def test_backend_set_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue") self.assertEqual("dummyValue", region.get(random_key)) def test_backend_set_data_with_string_as_valid_ttl(self): self.arguments['mongo_ttl_seconds'] = '3600' region = dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) self.assertEqual(region.backend.api.ttl_seconds, 3600) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue") self.assertEqual("dummyValue", region.get(random_key)) def test_backend_set_data_with_int_as_valid_ttl(self): self.arguments['mongo_ttl_seconds'] = 1800 region = dp_region.make_region().configure('keystone.cache.mongo', arguments=self.arguments) self.assertEqual(region.backend.api.ttl_seconds, 1800) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue") self.assertEqual("dummyValue", region.get(random_key)) def test_backend_set_none_as_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex region.set(random_key, None) self.assertEqual(None, region.get(random_key)) def test_backend_set_blank_as_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex region.set(random_key, "") self.assertEqual("", region.get(random_key)) def test_backend_set_same_key_multiple_times(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue") self.assertEqual("dummyValue", region.get(random_key)) dict_value = {'key1': 'value1'} region.set(random_key, dict_value) self.assertEqual(dict_value, region.get(random_key)) region.set(random_key, "dummyValue2") self.assertEqual("dummyValue2", region.get(random_key)) def test_backend_multi_set_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex random_key1 = uuid.uuid4().hex random_key2 = uuid.uuid4().hex random_key3 = uuid.uuid4().hex mapping = {random_key1: 'dummyValue1', random_key2: 'dummyValue2', random_key3: 'dummyValue3'} region.set_multi(mapping) # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, region.get(random_key)) self.assertFalse(region.get(random_key)) self.assertEqual("dummyValue1", region.get(random_key1)) self.assertEqual("dummyValue2", region.get(random_key2)) self.assertEqual("dummyValue3", region.get(random_key3)) def test_backend_multi_get_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex random_key1 = uuid.uuid4().hex random_key2 = uuid.uuid4().hex random_key3 = uuid.uuid4().hex mapping = {random_key1: 'dummyValue1', random_key2: '', random_key3: 'dummyValue3'} region.set_multi(mapping) keys = [random_key, random_key1, random_key2, random_key3] results = region.get_multi(keys) # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, results[0]) self.assertEqual("dummyValue1", results[1]) self.assertEqual("", results[2]) self.assertEqual("dummyValue3", results[3]) def test_backend_multi_set_should_update_existing(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex random_key1 = uuid.uuid4().hex random_key2 = uuid.uuid4().hex random_key3 = uuid.uuid4().hex mapping = {random_key1: 'dummyValue1', random_key2: 'dummyValue2', random_key3: 'dummyValue3'} region.set_multi(mapping) # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, region.get(random_key)) self.assertEqual("dummyValue1", region.get(random_key1)) self.assertEqual("dummyValue2", region.get(random_key2)) self.assertEqual("dummyValue3", region.get(random_key3)) mapping = {random_key1: 'dummyValue4', random_key2: 'dummyValue5'} region.set_multi(mapping) self.assertEqual(api.NO_VALUE, region.get(random_key)) self.assertEqual("dummyValue4", region.get(random_key1)) self.assertEqual("dummyValue5", region.get(random_key2)) self.assertEqual("dummyValue3", region.get(random_key3)) def test_backend_multi_set_get_with_blanks_none(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex random_key1 = uuid.uuid4().hex random_key2 = uuid.uuid4().hex random_key3 = uuid.uuid4().hex random_key4 = uuid.uuid4().hex mapping = {random_key1: 'dummyValue1', random_key2: None, random_key3: '', random_key4: 'dummyValue4'} region.set_multi(mapping) # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, region.get(random_key)) self.assertEqual("dummyValue1", region.get(random_key1)) self.assertEqual(None, region.get(random_key2)) self.assertEqual("", region.get(random_key3)) self.assertEqual("dummyValue4", region.get(random_key4)) keys = [random_key, random_key1, random_key2, random_key3, random_key4] results = region.get_multi(keys) # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, results[0]) self.assertEqual("dummyValue1", results[1]) self.assertEqual(None, results[2]) self.assertEqual("", results[3]) self.assertEqual("dummyValue4", results[4]) mapping = {random_key1: 'dummyValue5', random_key2: 'dummyValue6'} region.set_multi(mapping) self.assertEqual(api.NO_VALUE, region.get(random_key)) self.assertEqual("dummyValue5", region.get(random_key1)) self.assertEqual("dummyValue6", region.get(random_key2)) self.assertEqual("", region.get(random_key3)) def test_backend_delete_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue") self.assertEqual("dummyValue", region.get(random_key)) region.delete(random_key) # should return NO_VALUE as key no longer exists in cache self.assertEqual(api.NO_VALUE, region.get(random_key)) def test_backend_multi_delete_data(self): region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) random_key = uuid.uuid4().hex random_key1 = uuid.uuid4().hex random_key2 = uuid.uuid4().hex random_key3 = uuid.uuid4().hex mapping = {random_key1: 'dummyValue1', random_key2: 'dummyValue2', random_key3: 'dummyValue3'} region.set_multi(mapping) # should return NO_VALUE as key does not exist in cache self.assertEqual(api.NO_VALUE, region.get(random_key)) self.assertEqual("dummyValue1", region.get(random_key1)) self.assertEqual("dummyValue2", region.get(random_key2)) self.assertEqual("dummyValue3", region.get(random_key3)) self.assertEqual(api.NO_VALUE, region.get("InvalidKey")) keys = mapping.keys() region.delete_multi(keys) self.assertEqual(api.NO_VALUE, region.get("InvalidKey")) # should return NO_VALUE as keys no longer exist in cache self.assertEqual(api.NO_VALUE, region.get(random_key1)) self.assertEqual(api.NO_VALUE, region.get(random_key2)) self.assertEqual(api.NO_VALUE, region.get(random_key3)) def test_additional_crud_method_arguments_support(self): """Additional arguments should works across find/insert/update.""" self.arguments['wtimeout'] = 30000 self.arguments['j'] = True self.arguments['continue_on_error'] = True self.arguments['secondary_acceptable_latency_ms'] = 60 region = dp_region.make_region().configure( 'keystone.cache.mongo', arguments=self.arguments ) # There is no proxy so can access MongoCacheBackend directly api_methargs = region.backend.api.meth_kwargs self.assertEqual(api_methargs['wtimeout'], 30000) self.assertEqual(api_methargs['j'], True) self.assertEqual(api_methargs['continue_on_error'], True) self.assertEqual(api_methargs['secondary_acceptable_latency_ms'], 60) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue1") self.assertEqual("dummyValue1", region.get(random_key)) region.set(random_key, "dummyValue2") self.assertEqual("dummyValue2", region.get(random_key)) random_key = uuid.uuid4().hex region.set(random_key, "dummyValue3") self.assertEqual("dummyValue3", region.get(random_key)) keystone-2014.1/keystone/tests/test_associate_project_endpoint_extension.py0000664000175400017540000004672412323716272030733 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import copy import uuid from keystone.common import sql from keystone.common.sql import migration_helpers from keystone import contrib from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common import importutils from keystone.tests import test_v3 class TestExtensionCase(test_v3.RestfulTestCase): EXTENSION_NAME = 'endpoint_filter' EXTENSION_TO_ADD = 'endpoint_filter_extension' def setup_database(self): super(TestExtensionCase, self).setup_database() package_name = '.'.join((contrib.__name__, self.EXTENSION_NAME)) package = importutils.import_module(package_name) abs_path = migration_helpers.find_migrate_repo(package) migration.db_version_control(sql.get_engine(), abs_path) migration.db_sync(sql.get_engine(), abs_path) def config_overrides(self): super(TestExtensionCase, self).config_overrides() self.config_fixture.config( group='catalog', driver='keystone.contrib.endpoint_filter.backends.catalog_sql.' 'EndpointFilterCatalog') def setUp(self): super(TestExtensionCase, self).setUp() self.default_request_url = ( '/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.default_domain_project_id, 'endpoint_id': self.endpoint_id}) class AssociateEndpointProjectFilterCRUDTestCase(TestExtensionCase): """Test OS-EP-FILTER endpoint to project associations extension.""" # endpoint-project associations crud tests # PUT def test_create_endpoint_project_assoc(self): """PUT /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Valid endpoint and project id test case. """ self.put(self.default_request_url, body='', expected_status=204) def test_create_endpoint_project_assoc_noproj(self): """PUT OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Invalid project id test case. """ self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': uuid.uuid4().hex, 'endpoint_id': self.endpoint_id}, body='', expected_status=404) def test_create_endpoint_project_assoc_noendp(self): """PUT /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Invalid endpoint id test case. """ self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.default_domain_project_id, 'endpoint_id': uuid.uuid4().hex}, body='', expected_status=404) def test_create_endpoint_project_assoc_unexpected_body(self): """PUT /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Unexpected body in request. The body should be ignored. """ self.put(self.default_request_url, body={'project_id': self.default_domain_project_id}, expected_status=204) # HEAD def test_check_endpoint_project_assoc(self): """HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Valid project and endpoint id test case. """ self.put(self.default_request_url, body='', expected_status=204) self.head('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.default_domain_project_id, 'endpoint_id': self.endpoint_id}, expected_status=204) def test_check_endpoint_project_assoc_noproj(self): """HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Invalid project id test case. """ self.put(self.default_request_url) self.head('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': uuid.uuid4().hex, 'endpoint_id': self.endpoint_id}, body='', expected_status=404) def test_check_endpoint_project_assoc_noendp(self): """HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Invalid endpoint id test case. """ self.put(self.default_request_url) self.head('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.default_domain_project_id, 'endpoint_id': uuid.uuid4().hex}, body='', expected_status=404) # GET def test_get_endpoint_project_assoc(self): """GET /OS-EP-FILTER/projects/{project_id}/endpoints success.""" self.put(self.default_request_url) r = self.get('/OS-EP-FILTER/projects/%(project_id)s/endpoints' % { 'project_id': self.default_domain_project_id}) self.assertValidEndpointListResponse(r, self.endpoint) def test_get_endpoint_project_assoc_noproj(self): """GET /OS-EP-FILTER/projects/{project_id}/endpoints no project.""" self.put(self.default_request_url) self.get('/OS-EP-FILTER/projects/%(project_id)s/endpoints' % { 'project_id': uuid.uuid4().hex}, body='', expected_status=404) def test_list_projects_for_endpoint_default(self): """GET /OS-EP-FILTER/endpoints/{endpoint_id}/projects success Don't associate project and endpoint, then get empty list. """ r = self.get('/OS-EP-FILTER/endpoints/%(endpoint_id)s/projects' % {'endpoint_id': self.endpoint_id}, expected_status=200) self.assertValidProjectListResponse(r, expected_length=0) def test_list_projects_for_endpoint_noendpoint(self): """GET /OS-EP-FILTER/endpoints/{endpoint_id}/projects Invalid endpoint id test case. """ self.get('/OS-EP-FILTER/endpoints/%(endpoint_id)s/projects' % {'endpoint_id': uuid.uuid4().hex}, expected_status=404) def test_list_projects_for_endpoint_assoc(self): """GET /OS-EP-FILTER/endpoints/{endpoint_id}/projects success Associate default project and endpoint, then get it. """ self.put(self.default_request_url) r = self.get('/OS-EP-FILTER/endpoints/%(endpoint_id)s/projects' % {'endpoint_id': self.endpoint_id}, expected_status=200) self.assertValidProjectListResponse(r, self.default_domain_project) # DELETE def test_remove_endpoint_project_assoc(self): """DELETE /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Valid project id and endpoint id test case. """ self.put(self.default_request_url) self.delete('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.default_domain_project_id, 'endpoint_id': self.endpoint_id}, expected_status=204) def test_remove_endpoint_project_assoc_noproj(self): """DELETE /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Invalid project id test case. """ self.put(self.default_request_url) self.delete('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': uuid.uuid4().hex, 'endpoint_id': self.endpoint_id}, body='', expected_status=404) def test_remove_endpoint_project_assoc_noendp(self): """DELETE /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id} Invalid endpoint id test case. """ self.put(self.default_request_url) self.delete('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.default_domain_project_id, 'endpoint_id': uuid.uuid4().hex}, body='', expected_status=404) class AssociateProjectEndpointFilterTokenRequestTestCase(TestExtensionCase): """Test OS-EP-FILTER catalog filtering extension.""" def test_default_project_id_scoped_token_with_user_id_ep_filter(self): # create a second project to work with ref = self.new_project_ref(domain_id=self.domain_id) r = self.post('/projects', body={'project': ref}) project = self.assertValidProjectResponse(r, ref) # grant the user a role on the project self.put( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'user_id': self.user['id'], 'project_id': project['id'], 'role_id': self.role['id']}) # set the user's preferred project body = {'user': {'default_project_id': project['id']}} r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body=body) self.assertValidUserResponse(r) # add one endpoint to the project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': project['id'], 'endpoint_id': self.endpoint_id}, body='', expected_status=204) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=True, endpoint_filter=True, ep_filter_assoc=1) self.assertEqual(r.result['token']['project']['id'], project['id']) def test_implicit_project_id_scoped_token_with_user_id_ep_filter(self): # attempt to authenticate without requesting a project # add one endpoint to default project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.project['id'], 'endpoint_id': self.endpoint_id}, body='', expected_status=204) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=True, endpoint_filter=True, ep_filter_assoc=1) self.assertEqual(r.result['token']['project']['id'], self.project['id']) def test_default_project_id_scoped_token_ep_filter_no_catalog(self): # create a second project to work with ref = self.new_project_ref(domain_id=self.domain_id) r = self.post('/projects', body={'project': ref}) project = self.assertValidProjectResponse(r, ref) # grant the user a role on the project self.put( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'user_id': self.user['id'], 'project_id': project['id'], 'role_id': self.role['id']}) # set the user's preferred project body = {'user': {'default_project_id': project['id']}} r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body=body) self.assertValidUserResponse(r) # add one endpoint to the project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': project['id'], 'endpoint_id': self.endpoint_id}, body='', expected_status=204) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens?nocatalog', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=False, endpoint_filter=True, ep_filter_assoc=1) self.assertEqual(r.result['token']['project']['id'], project['id']) def test_implicit_project_id_scoped_token_ep_filter_no_catalog(self): # attempt to authenticate without requesting a project # add one endpoint to default project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.project['id'], 'endpoint_id': self.endpoint_id}, body='', expected_status=204) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens?nocatalog', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=False, endpoint_filter=True, ep_filter_assoc=1) self.assertEqual(r.result['token']['project']['id'], self.project['id']) def test_default_project_id_scoped_token_ep_filter_full_catalog(self): # create a second project to work with ref = self.new_project_ref(domain_id=self.domain_id) r = self.post('/projects', body={'project': ref}) project = self.assertValidProjectResponse(r, ref) # grant the user a role on the project self.put( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'user_id': self.user['id'], 'project_id': project['id'], 'role_id': self.role['id']}) # set the user's preferred project body = {'user': {'default_project_id': project['id']}} r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body=body) self.assertValidUserResponse(r) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens?nocatalog', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=False, endpoint_filter=True) self.assertEqual(r.result['token']['project']['id'], project['id']) def test_implicit_project_id_scoped_token_ep_filter_full_catalog(self): # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens?nocatalog', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=False, endpoint_filter=True,) self.assertEqual(r.result['token']['project']['id'], self.project['id']) def test_implicit_project_id_scoped_token_handling_bad_reference(self): # handling the case with an endpoint that is not associate with # add first endpoint to default project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.project['id'], 'endpoint_id': self.endpoint_id}, body='', expected_status=204) # create a second temporary endpoint self.endpoint_id2 = uuid.uuid4().hex self.endpoint2 = self.new_endpoint_ref(service_id=self.service_id) self.endpoint2['id'] = self.endpoint_id2 self.catalog_api.create_endpoint( self.endpoint_id2, self.endpoint2.copy()) # add second endpoint to default project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.project['id'], 'endpoint_id': self.endpoint_id2}, body='', expected_status=204) # remove the temporary reference # this will create inconsistency in the endpoint filter table # which is fixed during the catalog creation for token request self.catalog_api.delete_endpoint(self.endpoint_id2) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse( r, require_catalog=True, endpoint_filter=True, ep_filter_assoc=1) self.assertEqual(r.result['token']['project']['id'], self.project['id']) def test_disabled_endpoint(self): """The catalog contains only enabled endpoints.""" # Add an enabled endpoint to the default project self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.project['id'], 'endpoint_id': self.endpoint_id}, expected_status=204) # Add a disabled endpoint to the default project. # Create a disabled endpoint that's like the enabled one. disabled_endpoint_ref = copy.copy(self.endpoint) disabled_endpoint_id = uuid.uuid4().hex disabled_endpoint_ref.update({ 'id': disabled_endpoint_id, 'enabled': False, 'interface': 'internal' }) self.catalog_api.create_endpoint(disabled_endpoint_id, disabled_endpoint_ref) self.put('/OS-EP-FILTER/projects/%(project_id)s' '/endpoints/%(endpoint_id)s' % { 'project_id': self.project['id'], 'endpoint_id': disabled_endpoint_id}, expected_status=204) # Authenticate to get token with catalog auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) endpoints = r.result['token']['catalog'][0]['endpoints'] endpoint_ids = [ep['id'] for ep in endpoints] self.assertEqual([self.endpoint_id], endpoint_ids) keystone-2014.1/keystone/tests/test_matchers.py0000664000175400017540000000372312323716272023034 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import textwrap import testtools from testtools.tests.matchers import helpers from keystone.tests import matchers class TestXMLEquals(testtools.TestCase, helpers.TestMatchersInterface): matches_xml = """ """ equivalent_xml = """ """ mismatches_xml = """ """ mismatches_description = textwrap.dedent("""\ expected = actual = """).lstrip() matches_matcher = matchers.XMLEquals(matches_xml) matches_matches = [matches_xml, equivalent_xml] matches_mismatches = [mismatches_xml] describe_examples = [ (mismatches_description, mismatches_xml, matches_matcher), ] str_examples = [('XMLEquals(%r)' % matches_xml, matches_matcher)] keystone-2014.1/keystone/tests/test_driver_hints.py0000664000175400017540000000443112323716272023723 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.tests import core as test from keystone.common import driver_hints class ListHintsTests(test.TestCase): def test_create_iterate_satisfy(self): hints = driver_hints.Hints() hints.add_filter('t1', 'data1') hints.add_filter('t2', 'data2') self.assertEqual(len(hints.filters()), 2) filter = hints.get_exact_filter_by_name('t1') self.assertEqual(filter['name'], 't1') self.assertEqual(filter['value'], 'data1') self.assertEqual(filter['comparator'], 'equals') self.assertEqual(filter['case_sensitive'], False) hints.remove(filter) filter_count = 0 for filter in hints.filters(): filter_count += 1 self.assertEqual(filter['name'], 't2') self.assertEqual(filter_count, 1) def test_multiple_creates(self): hints = driver_hints.Hints() hints.add_filter('t1', 'data1') hints.add_filter('t2', 'data2') self.assertEqual(len(hints.filters()), 2) hints2 = driver_hints.Hints() hints2.add_filter('t4', 'data1') hints2.add_filter('t5', 'data2') self.assertEqual(len(hints.filters()), 2) def test_limits(self): hints = driver_hints.Hints() self.assertIsNone(hints.get_limit()) hints.set_limit(10) self.assertEqual(hints.get_limit()['limit'], 10) self.assertFalse(hints.get_limit()['truncated']) hints.set_limit(11) self.assertEqual(hints.get_limit()['limit'], 11) self.assertFalse(hints.get_limit()['truncated']) hints.set_limit(10, truncated=True) self.assertEqual(hints.get_limit()['limit'], 10) self.assertTrue(hints.get_limit()['truncated']) keystone-2014.1/keystone/tests/ksfixtures/0000775000175400017540000000000012323716511022013 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/ksfixtures/appserver.py0000664000175400017540000000513012323716267024403 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from __future__ import absolute_import import fixtures from paste import deploy from keystone.common import environment from keystone import config CONF = config.CONF MAIN = 'main' ADMIN = 'admin' class AppServer(fixtures.Fixture): """A fixture for managing an application server instance. """ def __init__(self, config, name, cert=None, key=None, ca=None, cert_required=False, host='127.0.0.1', port=0): super(AppServer, self).__init__() self.config = config self.name = name self.cert = cert self.key = key self.ca = ca self.cert_required = cert_required self.host = host self.port = port def setUp(self): super(AppServer, self).setUp() app = deploy.loadapp(self.config, name=self.name) self.server = environment.Server(app, self.host, self.port) self._setup_SSL_if_requested() self.server.start(key='socket') # some tests need to know the port we ran on. self.port = self.server.socket_info['socket'][1] self._update_config_opt() self.addCleanup(self.server.kill) def _setup_SSL_if_requested(self): # TODO(dstanek): fix environment.Server to take a SSLOpts instance # so that the params are either always set or not if (self.cert is not None and self.ca is not None and self.key is not None): self.server.set_ssl(certfile=self.cert, keyfile=self.key, ca_certs=self.ca, cert_required=self.cert_required) def _update_config_opt(self): """Updates the config with the actual port used.""" opt_name = self._get_config_option_for_section_name() CONF.set_override(opt_name, self.port) def _get_config_option_for_section_name(self): """Maps Paster config section names to port option names.""" return {'admin': 'admin_port', 'main': 'public_port'}[self.name] keystone-2014.1/keystone/tests/ksfixtures/cache.py0000664000175400017540000000247712323716267023452 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import fixtures from keystone.common import cache class Cache(fixtures.Fixture): """A fixture for setting up and tearing down the cache between test cases. """ def setUp(self): # NOTE(dstanek): We must remove the existing cache backend in the # setUp instead of the tearDown because it defaults to a no-op cache # and we want the configure call below to create the correct backend. # NOTE(morganfainberg): The only way to reconfigure the CacheRegion # object on each setUp() call is to remove the .backend property. if hasattr(cache.REGION, 'backend'): del cache.REGION.backend # ensure the cache region instance is setup cache.configure_cache_region(cache.REGION) super(Cache, self).setUp() keystone-2014.1/keystone/tests/ksfixtures/__init__.py0000664000175400017540000000114412323716272024130 0ustar jenkinsjenkins00000000000000# 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 keystone.tests.ksfixtures.cache import Cache # flake8: noqa keystone-2014.1/keystone/tests/filtering.py0000664000175400017540000000622512323716267022156 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import uuid from keystone import config CONF = config.CONF class FilterTests(object): # Provide support for checking if a batch of list items all # exist within a contiguous range in a total list def _match_with_list(self, this_batch, total_list, batch_size=None, list_start=None, list_end=None): if batch_size is None: batch_size = len(this_batch) if list_start is None: list_start = 0 if list_end is None: list_end = len(total_list) for batch_item in range(0, batch_size): found = False for list_item in range(list_start, list_end): if this_batch[batch_item]['id'] == total_list[list_item]['id']: found = True self.assertTrue(found) def _create_entity(self, entity_type): f = getattr(self.identity_api, 'create_%s' % entity_type, None) if f is None: f = getattr(self.assignment_api, 'create_%s' % entity_type) return f def _delete_entity(self, entity_type): f = getattr(self.identity_api, 'delete_%s' % entity_type, None) if f is None: f = getattr(self.assignment_api, 'delete_%s' % entity_type) return f def _list_entities(self, entity_type): f = getattr(self.identity_api, 'list_%ss' % entity_type, None) if f is None: f = getattr(self.assignment_api, 'list_%ss' % entity_type) return f def _create_one_entity(self, entity_type, domain_id): new_entity = {'id': '0000' + uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain_id} self._create_entity(entity_type)(new_entity['id'], new_entity) return new_entity def _create_test_data(self, entity_type, number, domain_id=None): """Create entity test data :param entity_type: type of entity to create, e.g. 'user', group' etc. :param number: number of entities to create, :param domain_id: if not defined, all users will be created in the default domain. """ entity_list = [] if domain_id is None: domain_id = CONF.identity.default_domain_id for _ in range(number): new_entity = self._create_one_entity(entity_type, domain_id) entity_list.append(new_entity) return entity_list def _delete_test_data(self, entity_type, entity_list): for entity in entity_list: self._delete_entity(entity_type)(entity['id']) keystone-2014.1/keystone/tests/test_v3_policy.py0000664000175400017540000000466512323716267023147 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import uuid from keystone.tests import test_v3 class PolicyTestCase(test_v3.RestfulTestCase): """Test policy CRUD.""" def setUp(self): super(PolicyTestCase, self).setUp() self.policy_id = uuid.uuid4().hex self.policy = self.new_policy_ref() self.policy['id'] = self.policy_id self.policy_api.create_policy( self.policy_id, self.policy.copy()) # policy crud tests def test_create_policy(self): """Call ``POST /policies``.""" ref = self.new_policy_ref() r = self.post( '/policies', body={'policy': ref}) return self.assertValidPolicyResponse(r, ref) def test_list_policies(self): """Call ``GET /policies``.""" r = self.get('/policies') self.assertValidPolicyListResponse(r, ref=self.policy) def test_list_policies_xml(self): """Call ``GET /policies (xml data)``.""" r = self.get('/policies', content_type='xml') self.assertValidPolicyListResponse(r, ref=self.policy) def test_get_policy(self): """Call ``GET /policies/{policy_id}``.""" r = self.get( '/policies/%(policy_id)s' % { 'policy_id': self.policy_id}) self.assertValidPolicyResponse(r, self.policy) def test_update_policy(self): """Call ``PATCH /policies/{policy_id}``.""" policy = self.new_policy_ref() policy['id'] = self.policy_id r = self.patch( '/policies/%(policy_id)s' % { 'policy_id': self.policy_id}, body={'policy': policy}) self.assertValidPolicyResponse(r, policy) def test_delete_policy(self): """Call ``DELETE /policies/{policy_id}``.""" self.delete( '/policies/%(policy_id)s' % { 'policy_id': self.policy_id}) keystone-2014.1/keystone/tests/test_wsgi.py0000664000175400017540000003116712323716272022202 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import gettext import socket import uuid from babel import localedata import mock import webob from keystone.common import environment from keystone.common import wsgi from keystone import exception from keystone.openstack.common.fixture import moxstubout from keystone.openstack.common import gettextutils from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils from keystone import tests class FakeApp(wsgi.Application): def index(self, context): return {'a': 'b'} class BaseWSGITest(tests.TestCase): def setUp(self): self.app = FakeApp() super(BaseWSGITest, self).setUp() def _make_request(self, url='/'): req = webob.Request.blank(url) args = {'action': 'index', 'controller': None} req.environ['wsgiorg.routing_args'] = [None, args] return req class ApplicationTest(BaseWSGITest): def test_response_content_type(self): req = self._make_request() resp = req.get_response(self.app) self.assertEqual(resp.content_type, 'application/json') def test_query_string_available(self): class FakeApp(wsgi.Application): def index(self, context): return context['query_string'] req = self._make_request(url='/?1=2') resp = req.get_response(FakeApp()) self.assertEqual(jsonutils.loads(resp.body), {'1': '2'}) def test_headers_available(self): class FakeApp(wsgi.Application): def index(self, context): return context['headers'] app = FakeApp() req = self._make_request(url='/?1=2') req.headers['X-Foo'] = "bar" resp = req.get_response(app) self.assertIn('X-Foo', eval(resp.body)) def test_render_response(self): data = {'attribute': 'value'} body = '{"attribute": "value"}' resp = wsgi.render_response(body=data) self.assertEqual(resp.status, '200 OK') self.assertEqual(resp.status_int, 200) self.assertEqual(resp.body, body) self.assertEqual(resp.headers.get('Vary'), 'X-Auth-Token') self.assertEqual(resp.headers.get('Content-Length'), str(len(body))) def test_render_response_custom_status(self): resp = wsgi.render_response(status=(501, 'Not Implemented')) self.assertEqual(resp.status, '501 Not Implemented') self.assertEqual(resp.status_int, 501) def test_render_response_custom_headers(self): resp = wsgi.render_response(headers=[('Custom-Header', 'Some-Value')]) self.assertEqual(resp.headers.get('Custom-Header'), 'Some-Value') self.assertEqual(resp.headers.get('Vary'), 'X-Auth-Token') def test_render_response_no_body(self): resp = wsgi.render_response() self.assertEqual(resp.status, '204 No Content') self.assertEqual(resp.status_int, 204) self.assertEqual(resp.body, '') self.assertEqual(resp.headers.get('Content-Length'), '0') self.assertEqual(resp.headers.get('Content-Type'), None) def test_application_local_config(self): class FakeApp(wsgi.Application): def __init__(self, *args, **kwargs): self.kwargs = kwargs app = FakeApp.factory({}, testkey="test") self.assertIn("testkey", app.kwargs) self.assertEqual("test", app.kwargs["testkey"]) def test_render_exception(self): e = exception.Unauthorized(message=u'\u7f51\u7edc') resp = wsgi.render_exception(e) self.assertEqual(resp.status_int, 401) def test_render_exception_host(self): e = exception.Unauthorized(message=u'\u7f51\u7edc') context = {'host_url': 'http://%s:5000' % uuid.uuid4().hex} resp = wsgi.render_exception(e, context=context) self.assertEqual(resp.status_int, 401) class ExtensionRouterTest(BaseWSGITest): def test_extensionrouter_local_config(self): class FakeRouter(wsgi.ExtensionRouter): def __init__(self, *args, **kwargs): self.kwargs = kwargs factory = FakeRouter.factory({}, testkey="test") app = factory(self.app) self.assertIn("testkey", app.kwargs) self.assertEqual("test", app.kwargs["testkey"]) class MiddlewareTest(BaseWSGITest): def test_middleware_request(self): class FakeMiddleware(wsgi.Middleware): def process_request(self, req): req.environ['fake_request'] = True return req req = self._make_request() resp = FakeMiddleware(None)(req) self.assertIn('fake_request', resp.environ) def test_middleware_response(self): class FakeMiddleware(wsgi.Middleware): def process_response(self, request, response): response.environ = {} response.environ['fake_response'] = True return response req = self._make_request() resp = FakeMiddleware(self.app)(req) self.assertIn('fake_response', resp.environ) def test_middleware_bad_request(self): class FakeMiddleware(wsgi.Middleware): def process_response(self, request, response): raise exception.Unauthorized() req = self._make_request() req.environ['REMOTE_ADDR'] = '127.0.0.1' resp = FakeMiddleware(self.app)(req) self.assertEqual(resp.status_int, exception.Unauthorized.code) def test_middleware_type_error(self): class FakeMiddleware(wsgi.Middleware): def process_response(self, request, response): raise TypeError() req = self._make_request() req.environ['REMOTE_ADDR'] = '127.0.0.1' resp = FakeMiddleware(self.app)(req) # This is a validationerror type self.assertEqual(resp.status_int, exception.ValidationError.code) def test_middleware_exception_error(self): exception_str = 'EXCEPTIONERROR' class FakeMiddleware(wsgi.Middleware): def process_response(self, request, response): raise exception.UnexpectedError(exception_str) def do_request(): req = self._make_request() resp = FakeMiddleware(self.app)(req) self.assertEqual(resp.status_int, exception.UnexpectedError.code) return resp # Exception data should not be in the message when debug is False self.config_fixture.config(debug=False) self.assertNotIn(exception_str, do_request().body) # Exception data should be in the message when debug is True self.config_fixture.config(debug=True) self.assertIn(exception_str, do_request().body) def test_middleware_local_config(self): class FakeMiddleware(wsgi.Middleware): def __init__(self, *args, **kwargs): self.kwargs = kwargs factory = FakeMiddleware.factory({}, testkey="test") app = factory(self.app) self.assertIn("testkey", app.kwargs) self.assertEqual("test", app.kwargs["testkey"]) class LocalizedResponseTest(tests.TestCase): def setUp(self): super(LocalizedResponseTest, self).setUp() gettextutils._AVAILABLE_LANGUAGES.clear() self.addCleanup(gettextutils._AVAILABLE_LANGUAGES.clear) fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs def _set_expected_languages(self, all_locales=[], avail_locales=None): # Override localedata.locale_identifiers to return some locales. def returns_some_locales(*args, **kwargs): return all_locales self.stubs.Set(localedata, 'locale_identifiers', returns_some_locales) # Override gettext.find to return other than None for some languages. def fake_gettext_find(lang_id, *args, **kwargs): found_ret = '/keystone/%s/LC_MESSAGES/keystone.mo' % lang_id if avail_locales is None: # All locales are available. return found_ret languages = kwargs['languages'] if languages[0] in avail_locales: return found_ret return None self.stubs.Set(gettext, 'find', fake_gettext_find) def test_request_match_default(self): # The default language if no Accept-Language is provided is None req = webob.Request.blank('/') self.assertIsNone(wsgi.best_match_language(req)) def test_request_match_language_expected(self): # If Accept-Language is a supported language, best_match_language() # returns it. self._set_expected_languages(all_locales=['it']) req = webob.Request.blank('/', headers={'Accept-Language': 'it'}) self.assertEqual(wsgi.best_match_language(req), 'it') def test_request_match_language_unexpected(self): # If Accept-Language is a language we do not support, # best_match_language() returns None. self._set_expected_languages(all_locales=['it']) req = webob.Request.blank('/', headers={'Accept-Language': 'zh'}) self.assertIsNone(wsgi.best_match_language(req)) def test_static_translated_string_is_Message(self): # Statically created message strings are Message objects so that they # are lazy-translated. self.assertIsInstance(exception.Unauthorized.message_format, gettextutils.Message) def test_dynamic_translated_string_is_Message(self): # Dynamically created message strings are Message objects so that they # are lazy-translated. self.assertIsInstance(_('The resource could not be found.'), gettextutils.Message) class ServerTest(tests.TestCase): def setUp(self): super(ServerTest, self).setUp() environment.use_eventlet() self.host = '127.0.0.1' self.port = '1234' @mock.patch('eventlet.listen') @mock.patch('socket.getaddrinfo') def test_keepalive_unset(self, mock_getaddrinfo, mock_listen): mock_getaddrinfo.return_value = [(1, 2, 3, 4, 5)] mock_sock = mock.Mock() mock_sock.setsockopt = mock.Mock() mock_listen.return_value = mock_sock server = environment.Server(mock.MagicMock(), host=self.host, port=self.port) server.start() self.assertTrue(mock_listen.called) self.assertFalse(mock_sock.setsockopt.called) @mock.patch('eventlet.listen') @mock.patch('socket.getaddrinfo') def test_keepalive_set(self, mock_getaddrinfo, mock_listen): mock_getaddrinfo.return_value = [(1, 2, 3, 4, 5)] mock_sock = mock.Mock() mock_sock.setsockopt = mock.Mock() mock_listen.return_value = mock_sock server = environment.Server(mock.MagicMock(), host=self.host, port=self.port, keepalive=True) server.start() mock_sock.setsockopt.assert_called_once_with(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) self.assertTrue(mock_listen.called) @mock.patch('eventlet.listen') @mock.patch('socket.getaddrinfo') def test_keepalive_and_keepidle_set(self, mock_getaddrinfo, mock_listen): mock_getaddrinfo.return_value = [(1, 2, 3, 4, 5)] mock_sock = mock.Mock() mock_sock.setsockopt = mock.Mock() mock_listen.return_value = mock_sock server = environment.Server(mock.MagicMock(), host=self.host, port=self.port, keepalive=True, keepidle=1) server.start() # keepidle isn't available in the OS X version of eventlet if hasattr(socket, 'TCP_KEEPIDLE'): self.assertEqual(mock_sock.setsockopt.call_count, 2) # Test the last set of call args i.e. for the keepidle mock_sock.setsockopt.assert_called_with(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1) else: self.assertEqual(mock_sock.setsockopt.call_count, 1) self.assertTrue(mock_listen.called) keystone-2014.1/keystone/tests/test_singular_plural.py0000664000175400017540000000431012323716267024426 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import ast from keystone.contrib.admin_crud import core as admin_crud_core from keystone.contrib.s3 import core as s3_core from keystone.contrib.stats import core as stats_core from keystone.contrib.user_crud import core as user_crud_core from keystone.identity import core as identity_core from keystone import service class TestSingularPlural(object): def test_keyword_arg_condition_or_methods(self): """Raise if we see a keyword arg called 'condition' or 'methods'.""" modules = [admin_crud_core, s3_core, stats_core, user_crud_core, identity_core, service] for module in modules: filename = module.__file__ if filename.endswith(".pyc"): # In Python 2, the .py and .pyc files are in the same dir. filename = filename[:-1] with open(filename) as fil: source = fil.read() module = ast.parse(source, filename) last_stmt_or_expr = None for node in ast.walk(module): if isinstance(node, ast.stmt) or isinstance(node, ast.expr): # keyword nodes don't have line numbers, so we need to # get that information from the parent stmt or expr. last_stmt_or_expr = node elif isinstance(node, ast.keyword): for bad_word in ["condition", "methods"]: if node.arg == bad_word: raise AssertionError( "Suspicious name '%s' at %s line %s" % (bad_word, filename, last_stmt_or_expr.lineno)) keystone-2014.1/keystone/tests/unit/0000775000175400017540000000000012323716511020563 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/unit/common/0000775000175400017540000000000012323716511022053 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/unit/common/test_sql_core.py0000664000175400017540000000364012323716272025302 0ustar jenkinsjenkins00000000000000# 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 sqlalchemy.ext import declarative import testtools from keystone.common import sql from keystone.tests import utils ModelBase = declarative.declarative_base() class TestModel(ModelBase, sql.ModelDictMixin): __tablename__ = 'testmodel' id = sql.Column(sql.String(64), primary_key=True) text = sql.Column(sql.String(64), nullable=False) class TestModelDictMixin(testtools.TestCase): def test_creating_a_model_instance_from_a_dict(self): d = {'id': utils.new_uuid(), 'text': utils.new_uuid()} m = TestModel.from_dict(d) self.assertEqual(m.id, d['id']) self.assertEqual(m.text, d['text']) def test_creating_a_dict_from_a_model_instance(self): m = TestModel(id=utils.new_uuid(), text=utils.new_uuid()) d = m.to_dict() self.assertEqual(m.id, d['id']) self.assertEqual(m.text, d['text']) def test_creating_a_model_instance_from_an_invalid_dict(self): d = {'id': utils.new_uuid(), 'text': utils.new_uuid(), 'extra': None} self.assertRaises(TypeError, TestModel.from_dict, d) def test_creating_a_dict_from_a_model_instance_that_has_extra_attrs(self): expected = {'id': utils.new_uuid(), 'text': utils.new_uuid()} m = TestModel(id=expected['id'], text=expected['text']) m.extra = 'this should not be in the dictionary' self.assertEqual(m.to_dict(), expected) keystone-2014.1/keystone/tests/unit/common/test_utils.py0000664000175400017540000000354012323716272024632 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid import testtools from keystone.common import utils class TestPasswordHashing(testtools.TestCase): def setUp(self): super(TestPasswordHashing, self).setUp() self.password = uuid.uuid4().hex self.hashed_password = utils.hash_password(self.password) def test_that_we_can_verify_a_password_against_a_hash(self): self.assertTrue(utils.check_password(self.password, self.hashed_password)) def test_that_an_incorrect_password_fails_to_validate(self): bad_password = uuid.uuid4().hex self.assertFalse(utils.check_password(bad_password, self.hashed_password)) def test_that_a_hash_can_not_be_validated_against_a_hash(self): # NOTE(dstanek): Bug 1279849 reported a problem where passwords # were not being hashed if they already looked like a hash. This # would allow someone to hash their password ahead of time # (potentially getting around password requirements, like # length) and then they could auth with their original password. new_hashed_password = utils.hash_password(self.hashed_password) self.assertFalse(utils.check_password(self.password, new_hashed_password)) keystone-2014.1/keystone/tests/unit/common/__init__.py0000664000175400017540000000000012323716267024162 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/unit/identity/0000775000175400017540000000000012323716511022414 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/unit/identity/test_core.py0000664000175400017540000000403312323716272024761 0ustar jenkinsjenkins00000000000000# 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. """Unit tests for core identity behavior.""" import os import uuid import mock import testtools from keystone import config from keystone import exception from keystone import identity from keystone import tests CONF = config.CONF class TestDomainConfigs(testtools.TestCase): def setUp(self): super(TestDomainConfigs, self).setUp() self.addCleanup(CONF.reset) self.tmp_dir = tests.dirs.tmp() CONF.set_override('domain_config_dir', self.tmp_dir, 'identity') def test_config_for_nonexistent_domain(self): """Having a config for a non-existent domain will be ignored. There are no assertions in this test because there are no side effects. If there is a config file for a domain that does not exist it should be ignored. """ domain_id = uuid.uuid4().hex domain_config_filename = os.path.join(self.tmp_dir, 'keystone.%s.conf' % domain_id) self.addCleanup(lambda: os.remove(domain_config_filename)) with open(domain_config_filename, 'w'): """Write an empty config file.""" e = exception.DomainNotFound(domain_id=domain_id) mock_assignment_api = mock.Mock() mock_assignment_api.get_domain_by_name.side_effect = e domain_config = identity.DomainConfigs() fake_standard_driver = None domain_config.setup_domain_drivers(fake_standard_driver, mock_assignment_api) keystone-2014.1/keystone/tests/unit/identity/__init__.py0000664000175400017540000000000012323716267024523 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/unit/__init__.py0000664000175400017540000000000012323716267022672 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/tests/mapping_fixtures.py0000664000175400017540000002622412323716267023560 0ustar jenkinsjenkins00000000000000# 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. """Fixtures for Federation Mapping.""" EMPLOYEE_GROUP_ID = "0cd5e9" CONTRACTOR_GROUP_ID = "85a868" TESTER_GROUP_ID = "123" DEVELOPER_GROUP_ID = "xyz" # Mapping summary: # LastName Smith & Not Contractor or SubContractor -> group 0cd5e9 # FirstName Jill & Contractor or SubContractor -> to group 85a868 MAPPING_SMALL = { "rules": [ { "local": [ { "group": { "id": EMPLOYEE_GROUP_ID } }, { "user": { "name": "{0}" } } ], "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "not_any_of": [ "Contractor", "SubContractor" ] }, { "type": "LastName", "any_one_of": [ "Bo" ] } ] }, { "local": [ { "group": { "id": CONTRACTOR_GROUP_ID } }, { "user": { "name": "{0}" } } ], "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "any_one_of": [ "Contractor", "SubContractor" ] }, { "type": "FirstName", "any_one_of": [ "Jill" ] } ] } ] } # Mapping summary: # orgPersonType Admin or Big Cheese -> name {0} {1} email {2} and group 0cd5e9 # orgPersonType Customer -> user name {0} email {1} # orgPersonType Test and email ^@example.com$ -> group 123 and xyz MAPPING_LARGE = { "rules": [ { "local": [ { "user": { "name": "{0} {1}", "email": "{2}" }, "group": { "id": EMPLOYEE_GROUP_ID } } ], "remote": [ { "type": "FirstName" }, { "type": "LastName" }, { "type": "Email" }, { "type": "orgPersonType", "any_one_of": [ "Admin", "Big Cheese" ] } ] }, { "local": [ { "user": { "name": "{0}", "email": "{1}" } } ], "remote": [ { "type": "UserName" }, { "type": "Email" }, { "type": "orgPersonType", "not_any_of": [ "Admin", "Employee", "Contractor", "Tester" ] } ] }, { "local": [ { "group": { "id": TESTER_GROUP_ID } }, { "group": { "id": DEVELOPER_GROUP_ID } }, { "user": { "name": "{0}" } } ], "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "any_one_of": [ "Tester" ] }, { "type": "Email", "any_one_of": [ ".*@example.com$" ], "regex": True } ] } ] } MAPPING_BAD_REQ = { "rules": [ { "local": [ { "user": "name" } ], "remote": [ { "type": "UserName", "bad_requirement": [ "Young" ] } ] } ] } MAPPING_BAD_VALUE = { "rules": [ { "local": [ { "user": "name" } ], "remote": [ { "type": "UserName", "any_one_of": "should_be_list" } ] } ] } MAPPING_NO_RULES = { 'rules': [] } MAPPING_NO_REMOTE = { "rules": [ { "local": [ { "user": "name" } ], "remote": [] } ] } MAPPING_MISSING_LOCAL = { "rules": [ { "remote": [ { "type": "UserName", "any_one_of": "should_be_list" } ] } ] } MAPPING_WRONG_TYPE = { "rules": [ { "local": [ { "user": "{1}" } ], "remote": [ { "not_type": "UserName" } ] } ] } MAPPING_MISSING_TYPE = { "rules": [ { "local": [ { "user": "{1}" } ], "remote": [ {} ] } ] } MAPPING_EXTRA_REMOTE_PROPS_NOT_ANY_OF = { "rules": [ { "local": [ { "group": { "id": "0cd5e9" } }, { "user": { "name": "{0}" } } ], "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "not_any_of": [ "SubContractor" ], "invalid_type": "xyz" } ] } ] } MAPPING_EXTRA_REMOTE_PROPS_ANY_ONE_OF = { "rules": [ { "local": [ { "group": { "id": "0cd5e9" } }, { "user": { "name": "{0}" } } ], "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "any_one_of": [ "SubContractor" ], "invalid_type": "xyz" } ] } ] } MAPPING_EXTRA_REMOTE_PROPS_JUST_TYPE = { "rules": [ { "local": [ { "group": { "id": "0cd5e9" } }, { "user": { "name": "{0}" } } ], "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "invalid_type": "xyz" } ] } ] } MAPPING_EXTRA_RULES_PROPS = { "rules": [ { "local": [ { "group": { "id": "0cd5e9" } }, { "user": { "name": "{0}" } } ], "invalid_type": { "id": "xyz", }, "remote": [ { "type": "UserName" }, { "type": "orgPersonType", "not_any_of": [ "SubContractor" ] } ] } ] } EMPLOYEE_ASSERTION = { 'Email': 'tim@example.com', 'UserName': 'tbo', 'FirstName': 'Tim', 'LastName': 'Bo', 'orgPersonType': 'Employee;BuildingX;' } EMPLOYEE_ASSERTION_PREFIXED = { 'PREFIX_Email': 'tim@example.com', 'PREFIX_UserName': 'tbo', 'PREFIX_FirstName': 'Tim', 'PREFIX_LastName': 'Bo', 'PREFIX_orgPersonType': 'SuperEmployee;BuildingX;' } CONTRACTOR_ASSERTION = { 'Email': 'jill@example.com', 'UserName': 'jsmith', 'FirstName': 'Jill', 'LastName': 'Smith', 'orgPersonType': 'Contractor;Non-Dev;' } ADMIN_ASSERTION = { 'Email': 'bob@example.com', 'UserName': 'bob', 'FirstName': 'Bob', 'LastName': 'Thompson', 'orgPersonType': 'Admin;Chief;' } CUSTOMER_ASSERTION = { 'Email': 'beth@example.com', 'UserName': 'bwilliams', 'FirstName': 'Beth', 'LastName': 'Williams', 'orgPersonType': 'Customer;' } TESTER_ASSERTION = { 'Email': 'testacct@example.com', 'UserName': 'testacct', 'FirstName': 'Test', 'LastName': 'Account', 'orgPersonType': 'Tester;' } BAD_TESTER_ASSERTION = { 'Email': 'eviltester@example.org', 'UserName': 'Evil', 'FirstName': 'Test', 'LastName': 'Account', 'orgPersonType': 'Tester;' } MALFORMED_TESTER_ASSERTION = { 'Email': 'testacct@example.com', 'UserName': 'testacct', 'FirstName': 'Test', 'LastName': 'Account', 'orgPersonType': 'Tester;', 'object': object(), 'dictionary': dict(zip('teststring', xrange(10))), 'tuple': tuple(xrange(5)) } CONTRACTOR_MALFORMED_ASSERTION = { 'UserName': 'user', 'FirstName': object(), 'orgPersonType': 'Contractor' } keystone-2014.1/keystone/tests/utils.py0000664000175400017540000000123712323716267021331 0ustar jenkinsjenkins00000000000000# 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. """Useful utilities for tests.""" import uuid def new_uuid(): """Return a string UUID.""" return uuid.uuid4().hex keystone-2014.1/keystone/tests/test_ldap_tls_livetest.py0000664000175400017540000001060012323716267024743 0ustar jenkinsjenkins00000000000000# Copyright 2013 OpenStack Foundation # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import ldap import ldap.modlist from keystone import config from keystone import exception from keystone import identity from keystone import tests from keystone.tests import test_ldap_livetest CONF = config.CONF def create_object(dn, attrs): conn = ldap.initialize(CONF.ldap.url) conn.simple_bind_s(CONF.ldap.user, CONF.ldap.password) ldif = ldap.modlist.addModlist(attrs) conn.add_s(dn, ldif) conn.unbind_s() class LiveTLSLDAPIdentity(test_ldap_livetest.LiveLDAPIdentity): def _ldap_skip_live(self): self.skip_if_env_not_set('ENABLE_TLS_LDAP_LIVE_TEST') def config_files(self): config_files = super(LiveTLSLDAPIdentity, self).config_files() config_files.append(tests.dirs.tests_conf('backend_tls_liveldap.conf')) return config_files def config_overrides(self): super(LiveTLSLDAPIdentity, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.ldap.Identity') def test_tls_certfile_demand_option(self): self.config_fixture.config(group='ldap', use_tls=True, tls_cacertdir=None, tls_req_cert='demand') self.identity_api = identity.backends.ldap.Identity() user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'tenants': ['bar']} self.identity_api.create_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual('fake1', user_ref['id']) user['password'] = 'fakepass2' self.identity_api.update_user('fake1', user) self.identity_api.delete_user('fake1') self.assertRaises(exception.UserNotFound, self.identity_api.get_user, 'fake1') def test_tls_certdir_demand_option(self): self.config_fixture.config(group='ldap', use_tls=True, tls_cacertdir=None, tls_req_cert='demand') self.identity_api = identity.backends.ldap.Identity() user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'tenants': ['bar']} self.identity_api.create_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual('fake1', user_ref['id']) user['password'] = 'fakepass2' self.identity_api.update_user('fake1', user) self.identity_api.delete_user('fake1') self.assertRaises(exception.UserNotFound, self.identity_api.get_user, 'fake1') def test_tls_bad_certfile(self): self.config_fixture.config( group='ldap', use_tls=True, tls_req_cert='demand', tls_cacertfile='/etc/keystone/ssl/certs/mythicalcert.pem', tls_cacertdir=None) self.identity_api = identity.backends.ldap.Identity() user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'tenants': ['bar']} self.assertRaises(IOError, self.identity_api.create_user, 'fake', user) def test_tls_bad_certdir(self): self.config_fixture.config( group='ldap', use_tls=True, tls_cacertfile=None, tls_req_cert='demand', tls_cacertdir='/etc/keystone/ssl/mythicalcertdir') self.identity_api = identity.backends.ldap.Identity() user = {'id': 'fake1', 'name': 'fake1', 'password': 'fakepass1', 'tenants': ['bar']} self.assertRaises(IOError, self.identity_api.create_user, 'fake', user) keystone-2014.1/keystone/tests/test_token_provider.py0000664000175400017540000007735612323716272024275 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import datetime from keystone import config from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import default_fixtures from keystone import token from keystone.token.providers import pki CONF = config.CONF FUTURE_DELTA = datetime.timedelta(seconds=CONF.token.expiration) CURRENT_DATE = timeutils.utcnow() SAMPLE_V2_TOKEN = { "access": { "trust": { "id": "abc123", "trustee_user_id": "123456" }, "serviceCatalog": [ { "endpoints": [ { "adminURL": "http://localhost:8774/v1.1/01257", "id": "51934fe63a5b4ac0a32664f64eb462c3", "internalURL": "http://localhost:8774/v1.1/01257", "publicURL": "http://localhost:8774/v1.1/01257", "region": "RegionOne" } ], "endpoints_links": [], "name": "nova", "type": "compute" }, { "endpoints": [ { "adminURL": "http://localhost:9292", "id": "aaa17a539e364297a7845d67c7c7cc4b", "internalURL": "http://localhost:9292", "publicURL": "http://localhost:9292", "region": "RegionOne" } ], "endpoints_links": [], "name": "glance", "type": "image" }, { "endpoints": [ { "adminURL": "http://localhost:8776/v1/01257", "id": "077d82df25304abeac2294004441db5a", "internalURL": "http://localhost:8776/v1/01257", "publicURL": "http://localhost:8776/v1/01257", "region": "RegionOne" } ], "endpoints_links": [], "name": "volume", "type": "volume" }, { "endpoints": [ { "adminURL": "http://localhost:8773/services/Admin", "id": "b06997fd08414903ad458836efaa9067", "internalURL": "http://localhost:8773/services/Cloud", "publicURL": "http://localhost:8773/services/Cloud", "region": "RegionOne" } ], "endpoints_links": [], "name": "ec2", "type": "ec2" }, { "endpoints": [ { "adminURL": "http://localhost:8080/v1", "id": "7bd0c643e05a4a2ab40902b2fa0dd4e6", "internalURL": "http://localhost:8080/v1/AUTH_01257", "publicURL": "http://localhost:8080/v1/AUTH_01257", "region": "RegionOne" } ], "endpoints_links": [], "name": "swift", "type": "object-store" }, { "endpoints": [ { "adminURL": "http://localhost:35357/v2.0", "id": "02850c5d1d094887bdc46e81e1e15dc7", "internalURL": "http://localhost:5000/v2.0", "publicURL": "http://localhost:5000/v2.0", "region": "RegionOne" } ], "endpoints_links": [], "name": "keystone", "type": "identity" } ], "token": { "expires": "2013-05-22T00:02:43.941430Z", "id": "ce4fc2d36eea4cc9a36e666ac2f1029a", "issued_at": "2013-05-21T00:02:43.941473Z", "tenant": { "enabled": True, "id": "01257", "name": "service" } }, "user": { "id": "f19ddbe2c53c46f189fe66d0a7a9c9ce", "name": "nova", "roles": [ { "name": "_member_" }, { "name": "admin" } ], "roles_links": [], "username": "nova" } } } SAMPLE_V3_TOKEN = { "token": { "catalog": [ { "endpoints": [ { "id": "02850c5d1d094887bdc46e81e1e15dc7", "interface": "admin", "region": "RegionOne", "url": "http://localhost:35357/v2.0" }, { "id": "446e244b75034a9ab4b0811e82d0b7c8", "interface": "internal", "region": "RegionOne", "url": "http://localhost:5000/v2.0" }, { "id": "47fa3d9f499240abb5dfcf2668f168cd", "interface": "public", "region": "RegionOne", "url": "http://localhost:5000/v2.0" } ], "id": "26d7541715a44a4d9adad96f9872b633", "type": "identity", }, { "endpoints": [ { "id": "aaa17a539e364297a7845d67c7c7cc4b", "interface": "admin", "region": "RegionOne", "url": "http://localhost:9292" }, { "id": "4fa9620e42394cb1974736dce0856c71", "interface": "internal", "region": "RegionOne", "url": "http://localhost:9292" }, { "id": "9673687f9bc441d88dec37942bfd603b", "interface": "public", "region": "RegionOne", "url": "http://localhost:9292" } ], "id": "d27a41843f4e4b0e8cf6dac4082deb0d", "type": "image", }, { "endpoints": [ { "id": "7bd0c643e05a4a2ab40902b2fa0dd4e6", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8080/v1" }, { "id": "43bef154594d4ccb8e49014d20624e1d", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8080/v1/AUTH_01257" }, { "id": "e63b5f5d7aa3493690189d0ff843b9b3", "interface": "public", "region": "RegionOne", "url": "http://localhost:8080/v1/AUTH_01257" } ], "id": "a669e152f1104810a4b6701aade721bb", "type": "object-store", }, { "endpoints": [ { "id": "51934fe63a5b4ac0a32664f64eb462c3", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8774/v1.1/01257" }, { "id": "869b535eea0d42e483ae9da0d868ebad", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8774/v1.1/01257" }, { "id": "93583824c18f4263a2245ca432b132a6", "interface": "public", "region": "RegionOne", "url": "http://localhost:8774/v1.1/01257" } ], "id": "7f32cc2af6c9476e82d75f80e8b3bbb8", "type": "compute", }, { "endpoints": [ { "id": "b06997fd08414903ad458836efaa9067", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8773/services/Admin" }, { "id": "411f7de7c9a8484c9b46c254fb2676e2", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8773/services/Cloud" }, { "id": "f21c93f3da014785854b4126d0109c49", "interface": "public", "region": "RegionOne", "url": "http://localhost:8773/services/Cloud" } ], "id": "b08c9c7d4ef543eba5eeb766f72e5aa1", "type": "ec2", }, { "endpoints": [ { "id": "077d82df25304abeac2294004441db5a", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8776/v1/01257" }, { "id": "875bf282362c40219665278b4fd11467", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8776/v1/01257" }, { "id": "cd229aa6df0640dc858a8026eb7e640c", "interface": "public", "region": "RegionOne", "url": "http://localhost:8776/v1/01257" } ], "id": "5db21b82617f4a95816064736a7bec22", "type": "volume", } ], "expires_at": "2013-05-22T00:02:43.941430Z", "issued_at": "2013-05-21T00:02:43.941473Z", "methods": [ "password" ], "project": { "domain": { "id": "default", "name": "Default" }, "id": "01257", "name": "service" }, "roles": [ { "id": "9fe2ff9ee4384b1894a90878d3e92bab", "name": "_member_" }, { "id": "53bff13443bd4450b97f978881d47b18", "name": "admin" } ], "user": { "domain": { "id": "default", "name": "Default" }, "id": "f19ddbe2c53c46f189fe66d0a7a9c9ce", "name": "nova" }, "OS-TRUST:trust": { "id": "abc123", "trustee_user_id": "123456", "trustor_user_id": "333333", "impersonation": False } } } SAMPLE_V2_TOKEN_WITH_EMBEDED_VERSION = { "access": { "trust": { "id": "abc123", "trustee_user_id": "123456" }, "serviceCatalog": [ { "endpoints": [ { "adminURL": "http://localhost:8774/v1.1/01257", "id": "51934fe63a5b4ac0a32664f64eb462c3", "internalURL": "http://localhost:8774/v1.1/01257", "publicURL": "http://localhost:8774/v1.1/01257", "region": "RegionOne" } ], "endpoints_links": [], "name": "nova", "type": "compute" }, { "endpoints": [ { "adminURL": "http://localhost:9292", "id": "aaa17a539e364297a7845d67c7c7cc4b", "internalURL": "http://localhost:9292", "publicURL": "http://localhost:9292", "region": "RegionOne" } ], "endpoints_links": [], "name": "glance", "type": "image" }, { "endpoints": [ { "adminURL": "http://localhost:8776/v1/01257", "id": "077d82df25304abeac2294004441db5a", "internalURL": "http://localhost:8776/v1/01257", "publicURL": "http://localhost:8776/v1/01257", "region": "RegionOne" } ], "endpoints_links": [], "name": "volume", "type": "volume" }, { "endpoints": [ { "adminURL": "http://localhost:8773/services/Admin", "id": "b06997fd08414903ad458836efaa9067", "internalURL": "http://localhost:8773/services/Cloud", "publicURL": "http://localhost:8773/services/Cloud", "region": "RegionOne" } ], "endpoints_links": [], "name": "ec2", "type": "ec2" }, { "endpoints": [ { "adminURL": "http://localhost:8080/v1", "id": "7bd0c643e05a4a2ab40902b2fa0dd4e6", "internalURL": "http://localhost:8080/v1/AUTH_01257", "publicURL": "http://localhost:8080/v1/AUTH_01257", "region": "RegionOne" } ], "endpoints_links": [], "name": "swift", "type": "object-store" }, { "endpoints": [ { "adminURL": "http://localhost:35357/v2.0", "id": "02850c5d1d094887bdc46e81e1e15dc7", "internalURL": "http://localhost:5000/v2.0", "publicURL": "http://localhost:5000/v2.0", "region": "RegionOne" } ], "endpoints_links": [], "name": "keystone", "type": "identity" } ], "token": { "expires": "2013-05-22T00:02:43.941430Z", "id": "ce4fc2d36eea4cc9a36e666ac2f1029a", "issued_at": "2013-05-21T00:02:43.941473Z", "tenant": { "enabled": True, "id": "01257", "name": "service" } }, "user": { "id": "f19ddbe2c53c46f189fe66d0a7a9c9ce", "name": "nova", "roles": [ { "name": "_member_" }, { "name": "admin" } ], "roles_links": [], "username": "nova" } }, 'token_version': 'v2.0' } SAMPLE_V3_TOKEN_WITH_EMBEDED_VERSION = { "token": { "catalog": [ { "endpoints": [ { "id": "02850c5d1d094887bdc46e81e1e15dc7", "interface": "admin", "region": "RegionOne", "url": "http://localhost:35357/v2.0" }, { "id": "446e244b75034a9ab4b0811e82d0b7c8", "interface": "internal", "region": "RegionOne", "url": "http://localhost:5000/v2.0" }, { "id": "47fa3d9f499240abb5dfcf2668f168cd", "interface": "public", "region": "RegionOne", "url": "http://localhost:5000/v2.0" } ], "id": "26d7541715a44a4d9adad96f9872b633", "type": "identity", }, { "endpoints": [ { "id": "aaa17a539e364297a7845d67c7c7cc4b", "interface": "admin", "region": "RegionOne", "url": "http://localhost:9292" }, { "id": "4fa9620e42394cb1974736dce0856c71", "interface": "internal", "region": "RegionOne", "url": "http://localhost:9292" }, { "id": "9673687f9bc441d88dec37942bfd603b", "interface": "public", "region": "RegionOne", "url": "http://localhost:9292" } ], "id": "d27a41843f4e4b0e8cf6dac4082deb0d", "type": "image", }, { "endpoints": [ { "id": "7bd0c643e05a4a2ab40902b2fa0dd4e6", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8080/v1" }, { "id": "43bef154594d4ccb8e49014d20624e1d", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8080/v1/AUTH_01257" }, { "id": "e63b5f5d7aa3493690189d0ff843b9b3", "interface": "public", "region": "RegionOne", "url": "http://localhost:8080/v1/AUTH_01257" } ], "id": "a669e152f1104810a4b6701aade721bb", "type": "object-store", }, { "endpoints": [ { "id": "51934fe63a5b4ac0a32664f64eb462c3", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8774/v1.1/01257" }, { "id": "869b535eea0d42e483ae9da0d868ebad", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8774/v1.1/01257" }, { "id": "93583824c18f4263a2245ca432b132a6", "interface": "public", "region": "RegionOne", "url": "http://localhost:8774/v1.1/01257" } ], "id": "7f32cc2af6c9476e82d75f80e8b3bbb8", "type": "compute", }, { "endpoints": [ { "id": "b06997fd08414903ad458836efaa9067", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8773/services/Admin" }, { "id": "411f7de7c9a8484c9b46c254fb2676e2", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8773/services/Cloud" }, { "id": "f21c93f3da014785854b4126d0109c49", "interface": "public", "region": "RegionOne", "url": "http://localhost:8773/services/Cloud" } ], "id": "b08c9c7d4ef543eba5eeb766f72e5aa1", "type": "ec2", }, { "endpoints": [ { "id": "077d82df25304abeac2294004441db5a", "interface": "admin", "region": "RegionOne", "url": "http://localhost:8776/v1/01257" }, { "id": "875bf282362c40219665278b4fd11467", "interface": "internal", "region": "RegionOne", "url": "http://localhost:8776/v1/01257" }, { "id": "cd229aa6df0640dc858a8026eb7e640c", "interface": "public", "region": "RegionOne", "url": "http://localhost:8776/v1/01257" } ], "id": "5db21b82617f4a95816064736a7bec22", "type": "volume", } ], "expires_at": "2013-05-22T00:02:43.941430Z", "issued_at": "2013-05-21T00:02:43.941473Z", "methods": [ "password" ], "project": { "domain": { "id": "default", "name": "Default" }, "id": "01257", "name": "service" }, "roles": [ { "id": "9fe2ff9ee4384b1894a90878d3e92bab", "name": "_member_" }, { "id": "53bff13443bd4450b97f978881d47b18", "name": "admin" } ], "user": { "domain": { "id": "default", "name": "Default" }, "id": "f19ddbe2c53c46f189fe66d0a7a9c9ce", "name": "nova" }, "OS-TRUST:trust": { "id": "abc123", "trustee_user_id": "123456", "trustor_user_id": "333333", "impersonation": False } }, 'token_version': 'v3.0' } def create_v2_token(): return { "access": { "token": { "expires": timeutils.isotime(CURRENT_DATE + FUTURE_DELTA), "issued_at": "2013-05-21T00:02:43.941473Z", "tenant": { "enabled": True, "id": "01257", "name": "service" } } } } SAMPLE_V2_TOKEN_EXPIRED = { "access": { "token": { "expires": timeutils.isotime(CURRENT_DATE), "issued_at": "2013-05-21T00:02:43.941473Z", "tenant": { "enabled": True, "id": "01257", "name": "service" } } } } def create_v3_token(): return { "token": { 'methods': [], "expires_at": timeutils.isotime(CURRENT_DATE + FUTURE_DELTA), "issued_at": "2013-05-21T00:02:43.941473Z", } } SAMPLE_V3_TOKEN_EXPIRED = { "token": { "expires_at": timeutils.isotime(CURRENT_DATE), "issued_at": "2013-05-21T00:02:43.941473Z", } } SAMPLE_MALFORMED_TOKEN = { "token": { "bogus": { "no expiration data": None } } } class TestTokenProvider(tests.TestCase): def setUp(self): super(TestTokenProvider, self).setUp() self.load_backends() def test_get_token_version(self): self.assertEqual( token.provider.V2, self.token_provider_api.get_token_version(SAMPLE_V2_TOKEN)) self.assertEqual( token.provider.V2, self.token_provider_api.get_token_version( SAMPLE_V2_TOKEN_WITH_EMBEDED_VERSION)) self.assertEqual( token.provider.V3, self.token_provider_api.get_token_version(SAMPLE_V3_TOKEN)) self.assertEqual( token.provider.V3, self.token_provider_api.get_token_version( SAMPLE_V3_TOKEN_WITH_EMBEDED_VERSION)) self.assertRaises(token.provider.UnsupportedTokenVersionException, self.token_provider_api.get_token_version, 'bogus') def test_token_format_provider_mismatch(self): self.config_fixture.config(group='signing', token_format='UUID') self.config_fixture.config(group='token', provider=token.provider.PKI_PROVIDER) try: token.provider.Manager() raise Exception( 'expecting ValueError on token provider misconfiguration') except exception.UnexpectedError: pass self.config_fixture.config(group='signing', token_format='PKI') self.config_fixture.config(group='token', provider=token.provider.UUID_PROVIDER) try: token.provider.Manager() raise Exception( 'expecting ValueError on token provider misconfiguration') except exception.UnexpectedError: pass # should be OK as token_format and provider aligns self.config_fixture.config(group='signing', token_format='PKI') self.config_fixture.config(group='token', provider=token.provider.PKI_PROVIDER) token.provider.Manager() self.config_fixture.config(group='signing', token_format='UUID') self.config_fixture.config(group='token', provider=token.provider.UUID_PROVIDER) token.provider.Manager() def test_default_token_format(self): self.assertEqual(token.provider.Manager.get_token_provider(), token.provider.PKI_PROVIDER) def test_uuid_token_format_and_no_provider(self): self.config_fixture.config(group='signing', token_format='UUID') self.assertEqual(token.provider.Manager.get_token_provider(), token.provider.UUID_PROVIDER) def test_default_providers_without_token_format(self): self.config_fixture.config(group='token', provider=token.provider.UUID_PROVIDER) token.provider.Manager() self.config_fixture.config(group='token', provider=token.provider.PKI_PROVIDER) token.provider.Manager() def test_unsupported_token_format(self): self.config_fixture.config(group='signing', token_format='CUSTOM') self.assertRaises(exception.UnexpectedError, token.provider.Manager.get_token_provider) def test_uuid_provider(self): self.config_fixture.config(group='token', provider=token.provider.UUID_PROVIDER) self.assertEqual(token.provider.Manager.get_token_provider(), token.provider.UUID_PROVIDER) def test_provider_override_token_format(self): self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Test') self.assertEqual(token.provider.Manager.get_token_provider(), 'keystone.token.providers.pki.Test') self.config_fixture.config(group='signing', token_format='UUID') self.config_fixture.config(group='token', provider=token.provider.UUID_PROVIDER) self.assertEqual(token.provider.Manager.get_token_provider(), token.provider.UUID_PROVIDER) self.config_fixture.config(group='signing', token_format='PKI') self.config_fixture.config(group='token', provider=token.provider.PKI_PROVIDER) self.assertEqual(token.provider.Manager.get_token_provider(), token.provider.PKI_PROVIDER) self.config_fixture.config(group='signing', token_format='CUSTOM') self.config_fixture.config(group='token', provider='my.package.MyProvider') self.assertEqual(token.provider.Manager.get_token_provider(), 'my.package.MyProvider') def test_provider_token_expiration_validation(self): self.assertRaises(exception.TokenNotFound, self.token_provider_api._is_valid_token, SAMPLE_V2_TOKEN_EXPIRED) self.assertRaises(exception.TokenNotFound, self.token_provider_api._is_valid_token, SAMPLE_V3_TOKEN_EXPIRED) self.assertRaises(exception.TokenNotFound, self.token_provider_api._is_valid_token, SAMPLE_MALFORMED_TOKEN) self.assertEqual( None, self.token_provider_api._is_valid_token(create_v2_token())) self.assertEqual( None, self.token_provider_api._is_valid_token(create_v3_token())) def test_uuid_provider_no_oauth_fails_oauth(self): self.load_fixtures(default_fixtures) self.config_fixture.config(group='token', provider=token.provider.UUID_PROVIDER) driver = token.provider.Manager().driver driver.oauth_api = None self.assertRaises(exception.Forbidden, driver.issue_v3_token, self.user_foo['id'], ['oauth1']) class TestPKIProvider(object): def setUp(self): super(TestPKIProvider, self).setUp() from keystoneclient.common import cms self.cms = cms from keystone.common import environment self.environment = environment old_cms_subprocess = cms.subprocess self.addCleanup(setattr, cms, 'subprocess', old_cms_subprocess) old_env_subprocess = environment.subprocess self.addCleanup(setattr, environment, 'subprocess', old_env_subprocess) self.cms.subprocess = self.target_subprocess self.environment.subprocess = self.target_subprocess reload(pki) # force module reload so the imports get re-evaluated def test_get_token_id_error_handling(self): # cause command-line failure self.config_fixture.config(group='signing', keyfile='--please-break-me') provider = pki.Provider() token_data = {} self.assertRaises(exception.UnexpectedError, provider._get_token_id, token_data) class TestPKIProviderWithEventlet(TestPKIProvider, tests.TestCase): def setUp(self): # force keystoneclient.common.cms to use eventlet's subprocess from eventlet.green import subprocess self.target_subprocess = subprocess super(TestPKIProviderWithEventlet, self).setUp() class TestPKIProviderWithStdlib(TestPKIProvider, tests.TestCase): def setUp(self): # force keystoneclient.common.cms to use the stdlib subprocess import subprocess self.target_subprocess = subprocess super(TestPKIProviderWithStdlib, self).setUp() keystone-2014.1/keystone/tests/test_keystoneclient_sql.py0000664000175400017540000004005312323716272025142 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import os import uuid from keystoneclient.contrib.ec2 import utils as ec2_utils from keystone import config from keystone import tests from keystone.tests import test_keystoneclient CONF = config.CONF class KcMasterSqlTestCase(test_keystoneclient.KcMasterTestCase): def config_files(self): config_files = super(KcMasterSqlTestCase, self).config_files() config_files.append(tests.dirs.tests_conf('backend_sql.conf')) return config_files def setUp(self): super(KcMasterSqlTestCase, self).setUp() self.default_client = self.get_client() self.addCleanup(self.cleanup_instance('default_client')) def test_endpoint_crud(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) service = client.services.create(name=uuid.uuid4().hex, service_type=uuid.uuid4().hex, description=uuid.uuid4().hex) endpoint_region = uuid.uuid4().hex invalid_service_id = uuid.uuid4().hex endpoint_publicurl = uuid.uuid4().hex endpoint_internalurl = uuid.uuid4().hex endpoint_adminurl = uuid.uuid4().hex # a non-existent service ID should trigger a 404 self.assertRaises(client_exceptions.NotFound, client.endpoints.create, region=endpoint_region, service_id=invalid_service_id, publicurl=endpoint_publicurl, adminurl=endpoint_adminurl, internalurl=endpoint_internalurl) endpoint = client.endpoints.create(region=endpoint_region, service_id=service.id, publicurl=endpoint_publicurl, adminurl=endpoint_adminurl, internalurl=endpoint_internalurl) self.assertEqual(endpoint.region, endpoint_region) self.assertEqual(endpoint.service_id, service.id) self.assertEqual(endpoint.publicurl, endpoint_publicurl) self.assertEqual(endpoint.internalurl, endpoint_internalurl) self.assertEqual(endpoint.adminurl, endpoint_adminurl) client.endpoints.delete(id=endpoint.id) self.assertRaises(client_exceptions.NotFound, client.endpoints.delete, id=endpoint.id) def _send_ec2_auth_request(self, credentials, client=None): if not client: client = self.default_client url = '%s/ec2tokens' % self.default_client.auth_url (resp, token) = client.request( url=url, method='POST', body={'credentials': credentials}) return resp, token def _generate_default_user_ec2_credentials(self): cred = self. default_client.ec2.create( user_id=self.user_foo['id'], tenant_id=self.tenant_bar['id']) return self._generate_user_ec2_credentials(cred.access, cred.secret) def _generate_user_ec2_credentials(self, access, secret): signer = ec2_utils.Ec2Signer(secret) credentials = {'params': {'SignatureVersion': '2'}, 'access': access, 'verb': 'GET', 'host': 'localhost', 'path': '/service/cloud'} signature = signer.generate(credentials) return credentials, signature def test_ec2_auth_success(self): credentials, signature = self._generate_default_user_ec2_credentials() credentials['signature'] = signature resp, token = self._send_ec2_auth_request(credentials) self.assertEqual(resp.status_code, 200) self.assertIn('access', token) def test_ec2_auth_success_trust(self): # Add "other" role user_foo and create trust delegating it to user_two self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_other['id']) trust_id = 'atrust123' trust = {'trustor_user_id': self.user_foo['id'], 'trustee_user_id': self.user_two['id'], 'project_id': self.tenant_bar['id'], 'impersonation': True} roles = [self.role_other] self.trust_api.create_trust(trust_id, trust, roles) # Create a client for user_two, scoped to the trust client = self.get_client(self.user_two) ret = client.authenticate(trust_id=trust_id, tenant_id=self.tenant_bar['id']) self.assertTrue(ret) self.assertTrue(client.auth_ref.trust_scoped) self.assertEqual(trust_id, client.auth_ref.trust_id) # Create an ec2 keypair using the trust client impersonating user_foo cred = client.ec2.create(user_id=self.user_foo['id'], tenant_id=self.tenant_bar['id']) credentials, signature = self._generate_user_ec2_credentials( cred.access, cred.secret) credentials['signature'] = signature resp, token = self._send_ec2_auth_request(credentials) self.assertEqual(resp.status_code, 200) self.assertEqual(trust_id, token['access']['trust']['id']) #TODO(shardy) we really want to check the roles and trustee # but because of where the stubbing happens we don't seem to # hit the necessary code in controllers.py _authenticate_token # so although all is OK via a real request, it incorrect in # this test.. def test_ec2_auth_failure(self): from keystoneclient import exceptions as client_exceptions credentials, signature = self._generate_default_user_ec2_credentials() credentials['signature'] = uuid.uuid4().hex self.assertRaises(client_exceptions.Unauthorized, self._send_ec2_auth_request, credentials) def test_ec2_credential_crud(self): creds = self.default_client.ec2.list(user_id=self.user_foo['id']) self.assertEqual(creds, []) cred = self.default_client.ec2.create(user_id=self.user_foo['id'], tenant_id=self.tenant_bar['id']) creds = self.default_client.ec2.list(user_id=self.user_foo['id']) self.assertEqual(creds, [cred]) got = self.default_client.ec2.get(user_id=self.user_foo['id'], access=cred.access) self.assertEqual(cred, got) self.default_client.ec2.delete(user_id=self.user_foo['id'], access=cred.access) creds = self.default_client.ec2.list(user_id=self.user_foo['id']) self.assertEqual(creds, []) def test_ec2_credential_crud_non_admin(self): na_client = self.get_client(self.user_two) creds = na_client.ec2.list(user_id=self.user_two['id']) self.assertEqual(creds, []) cred = na_client.ec2.create(user_id=self.user_two['id'], tenant_id=self.tenant_baz['id']) creds = na_client.ec2.list(user_id=self.user_two['id']) self.assertEqual(creds, [cred]) got = na_client.ec2.get(user_id=self.user_two['id'], access=cred.access) self.assertEqual(cred, got) na_client.ec2.delete(user_id=self.user_two['id'], access=cred.access) creds = na_client.ec2.list(user_id=self.user_two['id']) self.assertEqual(creds, []) def test_ec2_list_credentials(self): cred_1 = self.default_client.ec2.create( user_id=self.user_foo['id'], tenant_id=self.tenant_bar['id']) cred_2 = self.default_client.ec2.create( user_id=self.user_foo['id'], tenant_id=self.tenant_service['id']) cred_3 = self.default_client.ec2.create( user_id=self.user_foo['id'], tenant_id=self.tenant_mtu['id']) two = self.get_client(self.user_two) cred_4 = two.ec2.create(user_id=self.user_two['id'], tenant_id=self.tenant_bar['id']) creds = self.default_client.ec2.list(user_id=self.user_foo['id']) self.assertEqual(len(creds), 3) self.assertEqual(sorted([cred_1, cred_2, cred_3], key=lambda x: x.access), sorted(creds, key=lambda x: x.access)) self.assertNotIn(cred_4, creds) def test_ec2_credentials_create_404(self): from keystoneclient import exceptions as client_exceptions self.assertRaises(client_exceptions.NotFound, self.default_client.ec2.create, user_id=uuid.uuid4().hex, tenant_id=self.tenant_bar['id']) self.assertRaises(client_exceptions.NotFound, self.default_client.ec2.create, user_id=self.user_foo['id'], tenant_id=uuid.uuid4().hex) def test_ec2_credentials_delete_404(self): from keystoneclient import exceptions as client_exceptions self.assertRaises(client_exceptions.NotFound, self.default_client.ec2.delete, user_id=uuid.uuid4().hex, access=uuid.uuid4().hex) def test_ec2_credentials_get_404(self): from keystoneclient import exceptions as client_exceptions self.assertRaises(client_exceptions.NotFound, self.default_client.ec2.get, user_id=uuid.uuid4().hex, access=uuid.uuid4().hex) def test_ec2_credentials_list_404(self): from keystoneclient import exceptions as client_exceptions self.assertRaises(client_exceptions.NotFound, self.default_client.ec2.list, user_id=uuid.uuid4().hex) def test_ec2_credentials_list_user_forbidden(self): from keystoneclient import exceptions as client_exceptions two = self.get_client(self.user_two) self.assertRaises(client_exceptions.Forbidden, two.ec2.list, user_id=self.user_foo['id']) def test_ec2_credentials_get_user_forbidden(self): from keystoneclient import exceptions as client_exceptions cred = self.default_client.ec2.create(user_id=self.user_foo['id'], tenant_id=self.tenant_bar['id']) two = self.get_client(self.user_two) self.assertRaises(client_exceptions.Forbidden, two.ec2.get, user_id=self.user_foo['id'], access=cred.access) self.default_client.ec2.delete(user_id=self.user_foo['id'], access=cred.access) def test_ec2_credentials_delete_user_forbidden(self): from keystoneclient import exceptions as client_exceptions cred = self.default_client.ec2.create(user_id=self.user_foo['id'], tenant_id=self.tenant_bar['id']) two = self.get_client(self.user_two) self.assertRaises(client_exceptions.Forbidden, two.ec2.delete, user_id=self.user_foo['id'], access=cred.access) self.default_client.ec2.delete(user_id=self.user_foo['id'], access=cred.access) def test_endpoint_create_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.endpoints.create, region=uuid.uuid4().hex, service_id=uuid.uuid4().hex, publicurl=uuid.uuid4().hex, adminurl=uuid.uuid4().hex, internalurl=uuid.uuid4().hex) def test_endpoint_delete_404(self): from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) self.assertRaises(client_exceptions.NotFound, client.endpoints.delete, id=uuid.uuid4().hex) def test_policy_crud(self): # FIXME(dolph): this test was written prior to the v3 implementation of # the client and essentially refers to a non-existent # policy manager in the v2 client. this test needs to be # moved to a test suite running against the v3 api self.skipTest('Written prior to v3 client; needs refactor') from keystoneclient import exceptions as client_exceptions client = self.get_client(admin=True) policy_blob = uuid.uuid4().hex policy_type = uuid.uuid4().hex service = client.services.create( name=uuid.uuid4().hex, service_type=uuid.uuid4().hex, description=uuid.uuid4().hex) endpoint = client.endpoints.create( service_id=service.id, region=uuid.uuid4().hex, adminurl=uuid.uuid4().hex, internalurl=uuid.uuid4().hex, publicurl=uuid.uuid4().hex) # create policy = client.policies.create( blob=policy_blob, type=policy_type, endpoint=endpoint.id) self.assertEqual(policy_blob, policy.policy) self.assertEqual(policy_type, policy.type) self.assertEqual(endpoint.id, policy.endpoint_id) policy = client.policies.get(policy=policy.id) self.assertEqual(policy_blob, policy.policy) self.assertEqual(policy_type, policy.type) self.assertEqual(endpoint.id, policy.endpoint_id) endpoints = [x for x in client.endpoints.list() if x.id == endpoint.id] endpoint = endpoints[0] self.assertEqual(policy_blob, policy.policy) self.assertEqual(policy_type, policy.type) self.assertEqual(endpoint.id, policy.endpoint_id) # update policy_blob = uuid.uuid4().hex policy_type = uuid.uuid4().hex endpoint = client.endpoints.create( service_id=service.id, region=uuid.uuid4().hex, adminurl=uuid.uuid4().hex, internalurl=uuid.uuid4().hex, publicurl=uuid.uuid4().hex) policy = client.policies.update( policy=policy.id, blob=policy_blob, type=policy_type, endpoint=endpoint.id) policy = client.policies.get(policy=policy.id) self.assertEqual(policy_blob, policy.policy) self.assertEqual(policy_type, policy.type) self.assertEqual(endpoint.id, policy.endpoint_id) # delete client.policies.delete(policy=policy.id) self.assertRaises( client_exceptions.NotFound, client.policies.get, policy=policy.id) policies = [x for x in client.policies.list() if x.id == policy.id] self.assertEqual(len(policies), 0) class KcOptTestCase(KcMasterSqlTestCase): # Set KSCTEST_PATH to the keystoneclient directory, then run this test. # # For example, to test your local keystoneclient, # # KSCTEST_PATH=/opt/stack/python-keystoneclient \ # tox -e py27 test_keystoneclient_sql.KcOptTestCase def setUp(self): self.checkout_info = os.environ.get('KSCTEST_PATH') if not self.checkout_info: self.skip('Set KSCTEST_PATH env to test with local client') super(KcOptTestCase, self).setUp() keystone-2014.1/keystone/tests/fakeldap.py0000664000175400017540000003006012323716272021730 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """Fake LDAP server for test harness. This class does very little error checking, and knows nothing about ldap class definitions. It implements the minimum emulation of the python ldap library to work with nova. """ import re import shelve import ldap import six from six import moves from keystone.common import utils from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log SCOPE_NAMES = { ldap.SCOPE_BASE: 'SCOPE_BASE', ldap.SCOPE_ONELEVEL: 'SCOPE_ONELEVEL', ldap.SCOPE_SUBTREE: 'SCOPE_SUBTREE', } #http://msdn.microsoft.com/en-us/library/windows/desktop/aa366991(v=vs.85).aspx CONTROL_TREEDELETE = '1.2.840.113556.1.4.805' LOG = log.getLogger(__name__) def _process_attr(attr_name, value_or_values): attr_fn = lambda x: x def normalize_dn(dn): # Capitalize the attribute names as an LDAP server might. dn = ldap.dn.str2dn(dn) norm = [] for part in dn: name, val, i = part[0] name = name.upper() norm.append([(name, val, i)]) return ldap.dn.dn2str(norm) if attr_name in ('member', 'roleOccupant'): attr_fn = normalize_dn if isinstance(value_or_values, list): return [attr_fn(x) for x in value_or_values] return [attr_fn(value_or_values)] def _match_query(query, attrs): """Match an ldap query to an attribute dictionary. The characters &, |, and ! are supported in the query. No syntax checking is performed, so malformed queries will not work correctly. """ # cut off the parentheses inner = query[1:-1] if inner.startswith(('&', '|')): # cut off the & or | groups = _paren_groups(inner[1:]) return all(_match_query(group, attrs) for group in groups) if inner.startswith('!'): # cut off the ! and the nested parentheses return not _match_query(query[2:-1], attrs) (k, _sep, v) = inner.partition('=') return _match(k, v, attrs) def _paren_groups(source): """Split a string into parenthesized groups.""" count = 0 start = 0 result = [] for pos in moves.range(len(source)): if source[pos] == '(': if count == 0: start = pos count += 1 if source[pos] == ')': count -= 1 if count == 0: result.append(source[start:pos + 1]) return result def _match(key, value, attrs): """Match a given key and value against an attribute list.""" if key not in attrs: return False # This is a wild card search. Implemented as all or nothing for now. if value == '*': return True if key == 'serviceId': # for serviceId, the backend is returning a list of numbers # make sure we convert them to strings first before comparing # them str_sids = [str(x) for x in attrs[key]] return str(value) in str_sids if key != 'objectclass': return _process_attr(key, value)[0] in attrs[key] # it is an objectclass check, so check subclasses values = _subs(value) for v in values: if v in attrs[key]: return True return False def _subs(value): """Returns a list of subclass strings. The strings represent the ldap objectclass plus any subclasses that inherit from it. Fakeldap doesn't know about the ldap object structure, so subclasses need to be defined manually in the dictionary below. """ subs = {'groupOfNames': ['keystoneTenant', 'keystoneRole', 'keystoneTenantRole']} if value in subs: return [value] + subs[value] return [value] server_fail = False class FakeShelve(dict): def sync(self): pass FakeShelves = {} class FakeLdap(object): """Fake LDAP connection.""" __prefix = 'ldap:' def __init__(self, url, *args, **kwargs): LOG.debug('initialize url=%s', url) if url.startswith('fake://memory'): if url not in FakeShelves: FakeShelves[url] = FakeShelve() self.db = FakeShelves[url] else: self.db = shelve.open(url[7:]) def simple_bind_s(self, dn, password): """This method is ignored, but provided for compatibility.""" if server_fail: raise ldap.SERVER_DOWN LOG.debug('bind dn=%s', dn) if dn == 'cn=Admin' and password == 'password': return try: attrs = self.db['%s%s' % (self.__prefix, dn)] except KeyError: LOG.debug('bind fail: dn=%s not found', dn) raise ldap.NO_SUCH_OBJECT db_password = None try: db_password = attrs['userPassword'][0] except (KeyError, IndexError): LOG.debug('bind fail: password for dn=%s not found', dn) raise ldap.INAPPROPRIATE_AUTH if not utils.ldap_check_password(password, db_password): LOG.debug('bind fail: password for dn=%s does not match', dn) raise ldap.INVALID_CREDENTIALS def unbind_s(self): """This method is ignored, but provided for compatibility.""" if server_fail: raise ldap.SERVER_DOWN def add_s(self, dn, attrs): """Add an object with the specified attributes at dn.""" if server_fail: raise ldap.SERVER_DOWN # The LDAP API raises a TypeError if attr name is None. for k, dummy_v in attrs: if k is None: raise TypeError('must be string, not None. attrs=%s' % attrs) key = '%s%s' % (self.__prefix, dn) LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', { 'dn': dn, 'attrs': attrs}) if key in self.db: LOG.debug('add item failed: dn=%s is already in store.', dn) raise ldap.ALREADY_EXISTS(dn) self.db[key] = dict([(k, _process_attr(k, v)) for k, v in attrs]) self.db.sync() def delete_s(self, dn): """Remove the ldap object at specified dn.""" if server_fail: raise ldap.SERVER_DOWN key = '%s%s' % (self.__prefix, dn) LOG.debug('delete item: dn=%s', dn) try: del self.db[key] except KeyError: LOG.debug('delete item failed: dn=%s not found.', dn) raise ldap.NO_SUCH_OBJECT self.db.sync() def delete_ext_s(self, dn, serverctrls): """Remove the ldap object at specified dn.""" if server_fail: raise ldap.SERVER_DOWN try: if CONTROL_TREEDELETE in [c.controlType for c in serverctrls]: LOG.debug('FakeLdap subtree_delete item: dn=%s', dn) children = [k for k, v in six.iteritems(self.db) if re.match('%s.*,%s' % (self.__prefix, dn), k)] for c in children: del self.db[c] LOG.debug(_('FakeLdap delete item: dn=%s'), dn) key = '%s%s' % (self.__prefix, dn) del self.db[key] except KeyError: LOG.debug('delete item failed: dn=%s not found.', dn) raise ldap.NO_SUCH_OBJECT self.db.sync() def modify_s(self, dn, attrs): """Modify the object at dn using the attribute list. :param dn: an LDAP DN :param attrs: a list of tuples in the following form: ([MOD_ADD | MOD_DELETE | MOD_REPACE], attribute, value) """ if server_fail: raise ldap.SERVER_DOWN key = '%s%s' % (self.__prefix, dn) LOG.debug('modify item: dn=%(dn)s attrs=%(attrs)s', { 'dn': dn, 'attrs': attrs}) try: entry = self.db[key] except KeyError: LOG.debug('modify item failed: dn=%s not found.', dn) raise ldap.NO_SUCH_OBJECT for cmd, k, v in attrs: values = entry.setdefault(k, []) if cmd == ldap.MOD_ADD: v = _process_attr(k, v) for x in v: if x in values: raise ldap.TYPE_OR_VALUE_EXISTS values += v elif cmd == ldap.MOD_REPLACE: values[:] = _process_attr(k, v) elif cmd == ldap.MOD_DELETE: if v is None: if not values: LOG.debug('modify item failed: ' 'item has no attribute "%s" to delete', k) raise ldap.NO_SUCH_ATTRIBUTE values[:] = [] else: for val in _process_attr(k, v): try: values.remove(val) except ValueError: LOG.debug('modify item failed: ' 'item has no attribute "%(k)s" with ' 'value "%(v)s" to delete', { 'k': k, 'v': val}) raise ldap.NO_SUCH_ATTRIBUTE else: LOG.debug('modify item failed: unknown command %s', cmd) raise NotImplementedError('modify_s action %s not' ' implemented' % cmd) self.db[key] = entry self.db.sync() def search_s(self, dn, scope, query=None, fields=None): """Search for all matching objects under dn using the query. Args: dn -- dn to search under scope -- only SCOPE_BASE and SCOPE_SUBTREE are supported query -- query to filter objects by fields -- fields to return. Returns all fields if not specified """ if server_fail: raise ldap.SERVER_DOWN LOG.debug( 'search at dn=%(dn)s scope=%(scope)s query=%(query)s', {'dn': dn, 'scope': SCOPE_NAMES.get(scope, scope), 'query': query}) if scope == ldap.SCOPE_BASE: try: item_dict = self.db['%s%s' % (self.__prefix, dn)] except KeyError: LOG.debug('search fail: dn not found for SCOPE_BASE') raise ldap.NO_SUCH_OBJECT results = [(dn, item_dict)] elif scope == ldap.SCOPE_SUBTREE: results = [(k[len(self.__prefix):], v) for k, v in six.iteritems(self.db) if re.match('%s.*,%s' % (self.__prefix, dn), k)] elif scope == ldap.SCOPE_ONELEVEL: results = [(k[len(self.__prefix):], v) for k, v in six.iteritems(self.db) if re.match('%s\w+=[^,]+,%s' % (self.__prefix, dn), k)] else: LOG.debug('search fail: unknown scope %s', scope) raise NotImplementedError('Search scope %s not implemented.' % scope) objects = [] for dn, attrs in results: # filter the objects by query id_attr, id_val = dn.partition(',')[0].split('=', 1) match_attrs = attrs.copy() match_attrs[id_attr] = [id_val] if not query or _match_query(query, match_attrs): # filter the attributes by fields attrs = dict([(k, v) for k, v in six.iteritems(attrs) if not fields or k in fields]) objects.append((dn, attrs)) LOG.debug('search result: %s', objects) return objects keystone-2014.1/keystone/tests/test_middleware.py0000664000175400017540000001474212323716272023346 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import webob from keystone import config from keystone import middleware from keystone.openstack.common import jsonutils from keystone import tests CONF = config.CONF def make_request(**kwargs): accept = kwargs.pop('accept', None) method = kwargs.pop('method', 'GET') body = kwargs.pop('body', None) req = webob.Request.blank('/', **kwargs) req.method = method if body is not None: req.body = body if accept is not None: req.accept = accept return req def make_response(**kwargs): body = kwargs.pop('body', None) return webob.Response(body) class TokenAuthMiddlewareTest(tests.TestCase): def test_request(self): req = make_request() req.headers[middleware.AUTH_TOKEN_HEADER] = 'MAGIC' middleware.TokenAuthMiddleware(None).process_request(req) context = req.environ[middleware.CONTEXT_ENV] self.assertEqual(context['token_id'], 'MAGIC') class AdminTokenAuthMiddlewareTest(tests.TestCase): def test_request_admin(self): req = make_request() req.headers[middleware.AUTH_TOKEN_HEADER] = CONF.admin_token middleware.AdminTokenAuthMiddleware(None).process_request(req) context = req.environ[middleware.CONTEXT_ENV] self.assertTrue(context['is_admin']) def test_request_non_admin(self): req = make_request() req.headers[middleware.AUTH_TOKEN_HEADER] = 'NOT-ADMIN' middleware.AdminTokenAuthMiddleware(None).process_request(req) context = req.environ[middleware.CONTEXT_ENV] self.assertFalse(context['is_admin']) class PostParamsMiddlewareTest(tests.TestCase): def test_request_with_params(self): req = make_request(body="arg1=one", method='POST') middleware.PostParamsMiddleware(None).process_request(req) params = req.environ[middleware.PARAMS_ENV] self.assertEqual(params, {"arg1": "one"}) class JsonBodyMiddlewareTest(tests.TestCase): def test_request_with_params(self): req = make_request(body='{"arg1": "one", "arg2": ["a"]}', content_type='application/json', method='POST') middleware.JsonBodyMiddleware(None).process_request(req) params = req.environ[middleware.PARAMS_ENV] self.assertEqual(params, {"arg1": "one", "arg2": ["a"]}) def test_malformed_json(self): req = make_request(body='{"arg1": "on', content_type='application/json', method='POST') resp = middleware.JsonBodyMiddleware(None).process_request(req) self.assertEqual(resp.status_int, 400) def test_no_content_type(self): req = make_request(body='{"arg1": "one", "arg2": ["a"]}', method='POST') middleware.JsonBodyMiddleware(None).process_request(req) params = req.environ[middleware.PARAMS_ENV] self.assertEqual(params, {"arg1": "one", "arg2": ["a"]}) def test_unrecognized_content_type(self): req = make_request(body='{"arg1": "one", "arg2": ["a"]}', content_type='text/plain', method='POST') resp = middleware.JsonBodyMiddleware(None).process_request(req) self.assertEqual(resp.status_int, 400) def test_unrecognized_content_type_without_body(self): req = make_request(content_type='text/plain', method='GET') middleware.JsonBodyMiddleware(None).process_request(req) params = req.environ.get(middleware.PARAMS_ENV, {}) self.assertEqual(params, {}) class XmlBodyMiddlewareTest(tests.TestCase): def test_client_wants_xml_back(self): """Clients requesting XML should get what they ask for.""" body = '{"container": {"attribute": "value"}}' req = make_request(body=body, method='POST', accept='application/xml') middleware.XmlBodyMiddleware(None).process_request(req) resp = make_response(body=body) middleware.XmlBodyMiddleware(None).process_response(req, resp) self.assertEqual(resp.content_type, 'application/xml') def test_client_wants_json_back(self): """Clients requesting JSON should definitely not get XML back.""" body = '{"container": {"attribute": "value"}}' req = make_request(body=body, method='POST', accept='application/json') middleware.XmlBodyMiddleware(None).process_request(req) resp = make_response(body=body) middleware.XmlBodyMiddleware(None).process_response(req, resp) self.assertNotIn('application/xml', resp.content_type) def test_client_fails_to_specify_accept(self): """If client does not specify an Accept header, default to JSON.""" body = '{"container": {"attribute": "value"}}' req = make_request(body=body, method='POST') middleware.XmlBodyMiddleware(None).process_request(req) resp = make_response(body=body) middleware.XmlBodyMiddleware(None).process_response(req, resp) self.assertNotIn('application/xml', resp.content_type) def test_xml_replaced_by_json(self): """XML requests should be replaced by JSON requests.""" req = make_request( body='', content_type='application/xml', method='POST') middleware.XmlBodyMiddleware(None).process_request(req) self.assertEqual(req.content_type, 'application/json') self.assertTrue(jsonutils.loads(req.body)) def test_json_unnaffected(self): """JSON-only requests should be unaffected by the XML middleware.""" content_type = 'application/json' body = '{"container": {"attribute": "value"}}' req = make_request(body=body, content_type=content_type, method='POST') middleware.XmlBodyMiddleware(None).process_request(req) self.assertEqual(req.body, body) self.assertEqual(req.content_type, content_type) keystone-2014.1/keystone/tests/test_serializer.py0000664000175400017540000002603512323716267023404 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import copy from testtools import matchers from keystone.common import serializer from keystone import tests from keystone.tests import matchers as ksmatchers class XmlSerializerTestCase(tests.TestCase): def assertSerializeDeserialize(self, d, xml, xmlns=None): self.assertThat( serializer.to_xml(copy.deepcopy(d), xmlns), ksmatchers.XMLEquals(xml)) self.assertEqual(serializer.from_xml(xml), d) # operations should be invertible self.assertEqual( serializer.from_xml(serializer.to_xml(copy.deepcopy(d), xmlns)), d) self.assertThat( serializer.to_xml(serializer.from_xml(xml), xmlns), ksmatchers.XMLEquals(xml)) def test_auth_request(self): d = { "auth": { "passwordCredentials": { "username": "test_user", "password": "mypass" }, "tenantName": "customer-x" } } xml = """ """ self.assertSerializeDeserialize(d, xml) def test_role_crud(self): d = { "role": { "id": "123", "name": "Guest", "description": "Guest Access" } } # TODO(dolph): examples show this description as an attribute? xml = """ Guest Access """ self.assertSerializeDeserialize(d, xml) def test_service_crud(self): xmlns = "http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0" d = { "OS-KSADM:service": { "id": "123", "name": "nova", "type": "compute", "description": "OpenStack Compute Service" } } # TODO(dolph): examples show this description as an attribute? xml = """ OpenStack Compute Service """ % {'xmlns': xmlns} self.assertSerializeDeserialize(d, xml, xmlns=xmlns) def test_tenant_crud(self): d = { "tenant": { "id": "1234", "name": "ACME corp", "description": "A description...", "enabled": True } } xml = """ A description... """ self.assertSerializeDeserialize(d, xml) def test_tenant_crud_no_description(self): d = { "tenant": { "id": "1234", "name": "ACME corp", "description": "", "enabled": True } } xml = """ """ self.assertSerializeDeserialize(d, xml) def test_policy_list(self): d = {"policies": [{"id": "ab12cd"}]} xml = """ """ self.assertThat(serializer.to_xml(d), ksmatchers.XMLEquals(xml)) def test_values_list(self): d = { "objects": { "values": [{ "attribute": "value1", }, { "attribute": "value2", }] } } xml = """ """ self.assertThat(serializer.to_xml(d), ksmatchers.XMLEquals(xml)) def test_collection_list(self): d = { "links": { "next": "http://localhost:5000/v3/objects?page=3", "previous": None, "self": "http://localhost:5000/v3/objects" }, "objects": [{ "attribute": "value1", "links": { "self": "http://localhost:5000/v3/objects/abc123def", "anotherobj": "http://localhost:5000/v3/anotherobjs/123" } }, { "attribute": "value2", "links": { "self": "http://localhost:5000/v3/objects/abc456" } }]} xml = """ """ self.assertSerializeDeserialize(d, xml) def test_collection_member(self): d = { "object": { "attribute": "value", "links": { "self": "http://localhost:5000/v3/objects/abc123def", "anotherobj": "http://localhost:5000/v3/anotherobjs/123"}}} xml = """ """ self.assertSerializeDeserialize(d, xml) def test_v2_links_special_case(self): # There's special-case code (for backward compatibility) where if the # data is the v2 version data, the link elements are also added to the # main element. d = { "object": { "id": "v2.0", "status": "deprecated", "updated": "2014-04-17T00:00:00Z", "links": [{"href": "http://localhost:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-" "identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-" "identity-service/2.0/" "identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}] }} xml = """ """ self.assertThat(serializer.to_xml(d), ksmatchers.XMLEquals(xml)) def test_xml_with_namespaced_attribute_to_dict(self): expected = { "user": { "username": "test_user", "OS-KSADM:password": "mypass", }, } xmlns = 'http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0' xml = """ """ % dict(xmlns=xmlns) self.assertThat(serializer.from_xml(xml), matchers.Equals(expected)) keystone-2014.1/keystone/tests/test_s3_token_middleware.py0000664000175400017540000000274012323716272025146 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import testtools from keystoneclient.middleware import s3_token as ksc_s3_token from keystone.middleware import s3_token class S3TokenMiddlewareTestBase(testtools.TestCase): def test_symbols(self): """Verify s3_token middleware symbols. Verify that the keystone version of s3_token middleware forwards the public symbols from the keystoneclient version of the s3_token middleware for backwards compatibility. """ self.assertIs(ksc_s3_token.PROTOCOL_NAME, s3_token.PROTOCOL_NAME) self.assertIs(ksc_s3_token.split_path, s3_token.split_path) self.assertIs(ksc_s3_token.ServiceError, s3_token.ServiceError) self.assertIs(ksc_s3_token.filter_factory, s3_token.filter_factory) self.assertTrue( issubclass(s3_token.S3Token, ksc_s3_token.S3Token), 's3_token.S3Token is not subclass of keystoneclient s3_token') keystone-2014.1/keystone/tests/test_auth_plugin.py0000664000175400017540000001570612323716272023551 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import uuid from keystone import auth from keystone.common import config from keystone import exception from keystone import tests from keystone import token # for testing purposes only METHOD_NAME = 'simple_challenge_response' EXPECTED_RESPONSE = uuid.uuid4().hex DEMO_USER_ID = uuid.uuid4().hex class SimpleChallengeResponse(auth.AuthMethodHandler): method = METHOD_NAME def authenticate(self, context, auth_payload, user_context): if 'response' in auth_payload: if auth_payload['response'] != EXPECTED_RESPONSE: raise exception.Unauthorized('Wrong answer') user_context['user_id'] = DEMO_USER_ID else: return {"challenge": "What's the name of your high school?"} class DuplicateAuthPlugin(SimpleChallengeResponse): """Duplicate simple challenge response auth plugin.""" class MismatchedAuthPlugin(SimpleChallengeResponse): method = uuid.uuid4().hex class NoMethodAuthPlugin(auth.AuthMethodHandler): """An auth plugin that does not supply a method attribute.""" def authenticate(self, context, auth_payload, auth_context): pass class TestAuthPlugin(tests.SQLDriverOverrides, tests.TestCase): def setUp(self): super(TestAuthPlugin, self).setUp() self.load_backends() # need to register the token provider first because auth controller # depends on it token.provider.Manager() self.api = auth.controllers.Auth() def config_files(self): config_files = super(TestAuthPlugin, self).config_files() config_files.append(tests.dirs.tests_conf('test_auth_plugin.conf')) return config_files def config_overrides(self): super(TestAuthPlugin, self).config_overrides() self.config_fixture.config( group='auth', methods=[ 'keystone.auth.plugins.external.DefaultDomain', 'keystone.auth.plugins.password.Password', 'keystone.auth.plugins.token.Token', 'keystone.tests.test_auth_plugin.SimpleChallengeResponse']) def test_unsupported_auth_method(self): method_name = uuid.uuid4().hex auth_data = {'methods': [method_name]} auth_data[method_name] = {'test': 'test'} auth_data = {'identity': auth_data} self.assertRaises(exception.AuthMethodNotSupported, auth.controllers.AuthInfo.create, None, auth_data) def test_addition_auth_steps(self): auth_data = {'methods': [METHOD_NAME]} auth_data[METHOD_NAME] = { 'test': 'test'} auth_data = {'identity': auth_data} auth_info = auth.controllers.AuthInfo.create(None, auth_data) auth_context = {'extras': {}, 'method_names': []} try: self.api.authenticate({'environment': {}}, auth_info, auth_context) except exception.AdditionalAuthRequired as e: self.assertTrue('methods' in e.authentication) self.assertTrue(METHOD_NAME in e.authentication['methods']) self.assertTrue(METHOD_NAME in e.authentication) self.assertTrue('challenge' in e.authentication[METHOD_NAME]) # test correct response auth_data = {'methods': [METHOD_NAME]} auth_data[METHOD_NAME] = { 'response': EXPECTED_RESPONSE} auth_data = {'identity': auth_data} auth_info = auth.controllers.AuthInfo.create(None, auth_data) auth_context = {'extras': {}, 'method_names': []} self.api.authenticate({'environment': {}}, auth_info, auth_context) self.assertEqual(auth_context['user_id'], DEMO_USER_ID) # test incorrect response auth_data = {'methods': [METHOD_NAME]} auth_data[METHOD_NAME] = { 'response': uuid.uuid4().hex} auth_data = {'identity': auth_data} auth_info = auth.controllers.AuthInfo.create(None, auth_data) auth_context = {'extras': {}, 'method_names': []} self.assertRaises(exception.Unauthorized, self.api.authenticate, {'environment': {}}, auth_info, auth_context) class TestAuthPluginDynamicOptions(TestAuthPlugin): def config_overrides(self): super(TestAuthPluginDynamicOptions, self).config_overrides() # Clear the override for the [auth] ``methods`` option so it is # possible to load the options from the config file. self.config_fixture.conf.clear_override('methods', group='auth') def config_files(self): config_files = super(TestAuthPluginDynamicOptions, self).config_files() config_files.append(tests.dirs.tests_conf('test_auth_plugin.conf')) return config_files class TestInvalidAuthMethodRegistration(tests.TestCase): def test_duplicate_auth_method_registration(self): self.config_fixture.config( group='auth', methods=[ 'keystone.tests.test_auth_plugin.SimpleChallengeResponse', 'keystone.tests.test_auth_plugin.DuplicateAuthPlugin']) self.clear_auth_plugin_registry() self.assertRaises(ValueError, auth.controllers.load_auth_methods) def test_no_method_attribute_auth_method_by_class_name_registration(self): self.config_fixture.config( group='auth', methods=['keystone.tests.test_auth_plugin.NoMethodAuthPlugin']) self.clear_auth_plugin_registry() self.assertRaises(ValueError, auth.controllers.load_auth_methods) def test_mismatched_auth_method_and_plugin_attribute(self): test_opt = config.cfg.StrOpt('test') def clear_and_unregister_opt(): # NOTE(morganfainberg): Reset is required before unregistering # arguments or ArgsAlreadyParsedError is raised. config.CONF.reset() config.CONF.unregister_opt(test_opt, 'auth') self.addCleanup(clear_and_unregister_opt) # Guarantee we register the option we expect to unregister in cleanup config.CONF.register_opt(test_opt, 'auth') self.config_fixture.config(group='auth', methods=['test']) self.config_fixture.config( group='auth', test='keystone.tests.test_auth_plugin.MismatchedAuthPlugin') self.clear_auth_plugin_registry() self.assertRaises(ValueError, auth.controllers.load_auth_methods) keystone-2014.1/keystone/tests/test_sql_migrate_extensions.py0000664000175400017540000001732512323716267026023 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """ To run these tests against a live database: 1. Modify the file `tests/backend_sql.conf` to use the connection for your live database 2. Set up a blank, live database. 3. run the tests using :: ./run_tests.sh -N test_sql_upgrade WARNING:: Your database will be wiped. Do not do this against a Database with valuable data as all data will be lost. """ from keystone.contrib import endpoint_filter from keystone.contrib import example from keystone.contrib import federation from keystone.contrib import oauth1 from keystone.contrib import revoke from keystone.tests import test_sql_upgrade class SqlUpgradeExampleExtension(test_sql_upgrade.SqlMigrateBase): def repo_package(self): return example def test_upgrade(self): self.assertTableDoesNotExist('example') self.upgrade(1, repository=self.repo_path) self.assertTableColumns('example', ['id', 'type', 'extra']) def test_downgrade(self): self.upgrade(1, repository=self.repo_path) self.assertTableColumns('example', ['id', 'type', 'extra']) self.downgrade(0, repository=self.repo_path) self.assertTableDoesNotExist('example') class SqlUpgradeOAuth1Extension(test_sql_upgrade.SqlMigrateBase): def repo_package(self): return oauth1 def test_upgrade(self): self.assertTableDoesNotExist('consumer') self.assertTableDoesNotExist('request_token') self.assertTableDoesNotExist('access_token') self.upgrade(1, repository=self.repo_path) self.assertTableColumns('consumer', ['id', 'description', 'secret', 'extra']) self.assertTableColumns('request_token', ['id', 'request_secret', 'verifier', 'authorizing_user_id', 'requested_project_id', 'requested_roles', 'consumer_id', 'expires_at']) self.assertTableColumns('access_token', ['id', 'access_secret', 'authorizing_user_id', 'project_id', 'requested_roles', 'consumer_id', 'expires_at']) def test_downgrade(self): self.upgrade(1, repository=self.repo_path) self.assertTableColumns('consumer', ['id', 'description', 'secret', 'extra']) self.assertTableColumns('request_token', ['id', 'request_secret', 'verifier', 'authorizing_user_id', 'requested_project_id', 'requested_roles', 'consumer_id', 'expires_at']) self.assertTableColumns('access_token', ['id', 'access_secret', 'authorizing_user_id', 'project_id', 'requested_roles', 'consumer_id', 'expires_at']) self.downgrade(0, repository=self.repo_path) self.assertTableDoesNotExist('consumer') self.assertTableDoesNotExist('request_token') self.assertTableDoesNotExist('access_token') class EndpointFilterExtension(test_sql_upgrade.SqlMigrateBase): def repo_package(self): return endpoint_filter def test_upgrade(self): self.assertTableDoesNotExist('project_endpoint') self.upgrade(1, repository=self.repo_path) self.assertTableColumns('project_endpoint', ['endpoint_id', 'project_id']) def test_downgrade(self): self.upgrade(1, repository=self.repo_path) self.assertTableColumns('project_endpoint', ['endpoint_id', 'project_id']) self.downgrade(0, repository=self.repo_path) self.assertTableDoesNotExist('project_endpoint') class FederationExtension(test_sql_upgrade.SqlMigrateBase): """Test class for ensuring the Federation SQL.""" def setUp(self): super(FederationExtension, self).setUp() self.identity_provider = 'identity_provider' self.federation_protocol = 'federation_protocol' self.mapping = 'mapping' def repo_package(self): return federation def test_upgrade(self): self.assertTableDoesNotExist(self.identity_provider) self.assertTableDoesNotExist(self.federation_protocol) self.assertTableDoesNotExist(self.mapping) self.upgrade(1, repository=self.repo_path) self.assertTableColumns(self.identity_provider, ['id', 'enabled', 'description']) self.assertTableColumns(self.federation_protocol, ['id', 'idp_id', 'mapping_id']) self.upgrade(2, repository=self.repo_path) self.assertTableColumns(self.mapping, ['id', 'rules']) def test_downgrade(self): self.upgrade(2, repository=self.repo_path) self.assertTableColumns(self.identity_provider, ['id', 'enabled', 'description']) self.assertTableColumns(self.federation_protocol, ['id', 'idp_id', 'mapping_id']) self.assertTableColumns(self.mapping, ['id', 'rules']) self.downgrade(0, repository=self.repo_path) self.assertTableDoesNotExist(self.identity_provider) self.assertTableDoesNotExist(self.federation_protocol) self.assertTableDoesNotExist(self.mapping) _REVOKE_COLUMN_NAMES = ['id', 'domain_id', 'project_id', 'user_id', 'role_id', 'trust_id', 'consumer_id', 'access_token_id', 'issued_before', 'expires_at', 'revoked_at'] class RevokeExtension(test_sql_upgrade.SqlMigrateBase): def repo_package(self): return revoke def test_upgrade(self): self.assertTableDoesNotExist('revocation_event') self.upgrade(1, repository=self.repo_path) self.assertTableColumns('revocation_event', _REVOKE_COLUMN_NAMES) def test_downgrade(self): self.upgrade(1, repository=self.repo_path) self.assertTableColumns('revocation_event', _REVOKE_COLUMN_NAMES) self.downgrade(0, repository=self.repo_path) self.assertTableDoesNotExist('revocation_event') keystone-2014.1/keystone/tests/test_exception.py0000664000175400017540000001770512323716272023231 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import uuid import six from keystone.common import wsgi from keystone import config from keystone import exception from keystone.openstack.common import jsonutils from keystone import tests CONF = config.CONF class ExceptionTestCase(tests.TestCase): def assertValidJsonRendering(self, e): resp = wsgi.render_exception(e) self.assertEqual(resp.status_int, e.code) self.assertEqual(resp.status, '%s %s' % (e.code, e.title)) j = jsonutils.loads(resp.body) self.assertIsNotNone(j.get('error')) self.assertIsNotNone(j['error'].get('code')) self.assertIsNotNone(j['error'].get('title')) self.assertIsNotNone(j['error'].get('message')) self.assertNotIn('\n', j['error']['message']) self.assertNotIn(' ', j['error']['message']) self.assertTrue(type(j['error']['code']) is int) def test_all_json_renderings(self): """Everything callable in the exception module should be renderable. ... except for the base error class (exception.Error), which is not user-facing. This test provides a custom message to bypass docstring parsing, which should be tested separately. """ for cls in [x for x in exception.__dict__.values() if callable(x)]: if cls is not exception.Error and isinstance(cls, exception.Error): self.assertValidJsonRendering(cls(message='Overriden.')) def test_validation_error(self): target = uuid.uuid4().hex attribute = uuid.uuid4().hex e = exception.ValidationError(target=target, attribute=attribute) self.assertValidJsonRendering(e) self.assertIn(target, six.text_type(e)) self.assertIn(attribute, six.text_type(e)) def test_not_found(self): target = uuid.uuid4().hex e = exception.NotFound(target=target) self.assertValidJsonRendering(e) self.assertIn(target, six.text_type(e)) def test_403_title(self): e = exception.Forbidden() resp = wsgi.render_exception(e) j = jsonutils.loads(resp.body) self.assertEqual('Forbidden', e.title) self.assertEqual('Forbidden', j['error'].get('title')) def test_unicode_message(self): message = u'Comment \xe7a va' e = exception.Error(message) try: self.assertEqual(six.text_type(e), message) except UnicodeEncodeError: self.fail("unicode error message not supported") def test_unicode_string(self): e = exception.ValidationError(attribute='xx', target='Long \xe2\x80\x93 Dash') self.assertIn(u'\u2013', e.message) def test_invalid_unicode_string(self): # NOTE(jamielennox): This is a complete failure case so what is # returned in the e.message is not that important so long as there is # an error with a message e = exception.ValidationError(attribute='xx', target='\xe7a va') self.assertIn('%(attribute)', e.message) class UnexpectedExceptionTestCase(ExceptionTestCase): """Tests if internal info is exposed to the API user on UnexpectedError.""" class SubClassExc(exception.UnexpectedError): debug_message_format = 'Debug Message: %(debug_info)s' def setUp(self): super(UnexpectedExceptionTestCase, self).setUp() self.exc_str = uuid.uuid4().hex def test_unexpected_error_no_debug(self): self.config_fixture.config(debug=False) e = exception.UnexpectedError(exception=self.exc_str) self.assertNotIn(self.exc_str, six.text_type(e)) def test_unexpected_error_debug(self): self.config_fixture.config(debug=True) e = exception.UnexpectedError(exception=self.exc_str) self.assertIn(self.exc_str, six.text_type(e)) def test_unexpected_error_subclass_no_debug(self): self.config_fixture.config(debug=False) e = UnexpectedExceptionTestCase.SubClassExc( debug_info=self.exc_str) self.assertEqual(exception.UnexpectedError._message_format, six.text_type(e)) def test_unexpected_error_subclass_debug(self): self.config_fixture.config(debug=True) subclass = self.SubClassExc e = subclass(debug_info=self.exc_str) expected = subclass.debug_message_format % {'debug_info': self.exc_str} self.assertEqual(expected, six.text_type(e)) def test_unexpected_error_custom_message_no_debug(self): self.config_fixture.config(debug=False) e = exception.UnexpectedError(self.exc_str) self.assertEqual(exception.UnexpectedError._message_format, six.text_type(e)) def test_unexpected_error_custom_message_debug(self): self.config_fixture.config(debug=True) e = exception.UnexpectedError(self.exc_str) self.assertEqual(self.exc_str, six.text_type(e)) class SecurityErrorTestCase(ExceptionTestCase): """Tests whether security-related info is exposed to the API user.""" def test_unauthorized_exposure(self): self.config_fixture.config(debug=False) risky_info = uuid.uuid4().hex e = exception.Unauthorized(message=risky_info) self.assertValidJsonRendering(e) self.assertNotIn(risky_info, six.text_type(e)) def test_unauthorized_exposure_in_debug(self): self.config_fixture.config(debug=True) risky_info = uuid.uuid4().hex e = exception.Unauthorized(message=risky_info) self.assertValidJsonRendering(e) self.assertIn(risky_info, six.text_type(e)) def test_forbidden_exposure(self): self.config_fixture.config(debug=False) risky_info = uuid.uuid4().hex e = exception.Forbidden(message=risky_info) self.assertValidJsonRendering(e) self.assertNotIn(risky_info, six.text_type(e)) def test_forbidden_exposure_in_debug(self): self.config_fixture.config(debug=True) risky_info = uuid.uuid4().hex e = exception.Forbidden(message=risky_info) self.assertValidJsonRendering(e) self.assertIn(risky_info, six.text_type(e)) def test_forbidden_action_exposure(self): self.config_fixture.config(debug=False) risky_info = uuid.uuid4().hex action = uuid.uuid4().hex e = exception.ForbiddenAction(message=risky_info, action=action) self.assertValidJsonRendering(e) self.assertNotIn(risky_info, six.text_type(e)) self.assertIn(action, six.text_type(e)) e = exception.ForbiddenAction(action=risky_info) self.assertValidJsonRendering(e) self.assertIn(risky_info, six.text_type(e)) def test_forbidden_action_exposure_in_debug(self): self.config_fixture.config(debug=True) risky_info = uuid.uuid4().hex e = exception.ForbiddenAction(message=risky_info) self.assertValidJsonRendering(e) self.assertIn(risky_info, six.text_type(e)) e = exception.ForbiddenAction(action=risky_info) self.assertValidJsonRendering(e) self.assertIn(risky_info, six.text_type(e)) def test_unicode_argument_message(self): self.config_fixture.config(debug=False) risky_info = u'\u7ee7\u7eed\u884c\u7f29\u8fdb\u6216' e = exception.Forbidden(message=risky_info) self.assertValidJsonRendering(e) self.assertNotIn(risky_info, six.text_type(e)) keystone-2014.1/keystone/tests/test_ldap_livetest.py0000664000175400017540000002610212323716272024061 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import ldap import ldap.modlist import subprocess import uuid from keystone.common import ldap as ldap_common from keystone import config from keystone import exception from keystone.identity.backends import ldap as identity_ldap from keystone import tests from keystone.tests import test_backend_ldap CONF = config.CONF def create_object(dn, attrs): conn = ldap.initialize(CONF.ldap.url) conn.simple_bind_s(CONF.ldap.user, CONF.ldap.password) ldif = ldap.modlist.addModlist(attrs) conn.add_s(dn, ldif) conn.unbind_s() class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity): def setUp(self): self._ldap_skip_live() super(LiveLDAPIdentity, self).setUp() def _ldap_skip_live(self): self.skip_if_env_not_set('ENABLE_LDAP_LIVE_TEST') def clear_database(self): devnull = open('/dev/null', 'w') subprocess.call(['ldapdelete', '-x', '-D', CONF.ldap.user, '-H', CONF.ldap.url, '-w', CONF.ldap.password, '-r', CONF.ldap.suffix], stderr=devnull) if CONF.ldap.suffix.startswith('ou='): tree_dn_attrs = {'objectclass': 'organizationalUnit', 'ou': 'openstack'} else: tree_dn_attrs = {'objectclass': ['dcObject', 'organizationalUnit'], 'dc': 'openstack', 'ou': 'openstack'} create_object(CONF.ldap.suffix, tree_dn_attrs) create_object(CONF.ldap.user_tree_dn, {'objectclass': 'organizationalUnit', 'ou': 'Users'}) create_object(CONF.ldap.role_tree_dn, {'objectclass': 'organizationalUnit', 'ou': 'Roles'}) create_object(CONF.ldap.tenant_tree_dn, {'objectclass': 'organizationalUnit', 'ou': 'Projects'}) create_object(CONF.ldap.group_tree_dn, {'objectclass': 'organizationalUnit', 'ou': 'UserGroups'}) def config_files(self): config_files = super(LiveLDAPIdentity, self).config_files() config_files.append(tests.dirs.tests_conf('backend_liveldap.conf')) return config_files def config_overrides(self): super(LiveLDAPIdentity, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.ldap.Identity') def test_build_tree(self): """Regression test for building the tree names """ #logic is different from the fake backend. user_api = identity_ldap.UserApi(CONF) self.assertTrue(user_api) self.assertEqual(user_api.tree_dn, CONF.ldap.user_tree_dn) def tearDown(self): tests.TestCase.tearDown(self) def test_ldap_dereferencing(self): alt_users_ldif = {'objectclass': ['top', 'organizationalUnit'], 'ou': 'alt_users'} alt_fake_user_ldif = {'objectclass': ['person', 'inetOrgPerson'], 'cn': 'alt_fake1', 'sn': 'alt_fake1'} aliased_users_ldif = {'objectclass': ['alias', 'extensibleObject'], 'aliasedobjectname': "ou=alt_users,%s" % CONF.ldap.suffix} create_object("ou=alt_users,%s" % CONF.ldap.suffix, alt_users_ldif) create_object("%s=alt_fake1,ou=alt_users,%s" % (CONF.ldap.user_id_attribute, CONF.ldap.suffix), alt_fake_user_ldif) create_object("ou=alt_users,%s" % CONF.ldap.user_tree_dn, aliased_users_ldif) self.config_fixture.config(group='ldap', query_scope='sub', alias_dereferencing='never') self.identity_api = identity_ldap.Identity() self.assertRaises(exception.UserNotFound, self.identity_api.get_user, 'alt_fake1') self.config_fixture.config(group='ldap', alias_dereferencing='searching') self.identity_api = identity_ldap.Identity() user_ref = self.identity_api.get_user('alt_fake1') self.assertEqual(user_ref['id'], 'alt_fake1') self.config_fixture.config(group='ldap', alias_dereferencing='always') self.identity_api = identity_ldap.Identity() user_ref = self.identity_api.get_user('alt_fake1') self.assertEqual(user_ref['id'], 'alt_fake1') def test_base_ldap_connection_deref_option(self): deref = ldap_common.parse_deref('default') ldap_wrapper = ldap_common.LdapWrapper(CONF.ldap.url, CONF.ldap.page_size, alias_dereferencing=deref) self.assertEqual(ldap.get_option(ldap.OPT_DEREF), ldap_wrapper.conn.get_option(ldap.OPT_DEREF)) deref = ldap_common.parse_deref('always') ldap_wrapper = ldap_common.LdapWrapper(CONF.ldap.url, CONF.ldap.page_size, alias_dereferencing=deref) self.assertEqual(ldap.DEREF_ALWAYS, ldap_wrapper.conn.get_option(ldap.OPT_DEREF)) deref = ldap_common.parse_deref('finding') ldap_wrapper = ldap_common.LdapWrapper(CONF.ldap.url, CONF.ldap.page_size, alias_dereferencing=deref) self.assertEqual(ldap.DEREF_FINDING, ldap_wrapper.conn.get_option(ldap.OPT_DEREF)) deref = ldap_common.parse_deref('never') ldap_wrapper = ldap_common.LdapWrapper(CONF.ldap.url, CONF.ldap.page_size, alias_dereferencing=deref) self.assertEqual(ldap.DEREF_NEVER, ldap_wrapper.conn.get_option(ldap.OPT_DEREF)) deref = ldap_common.parse_deref('searching') ldap_wrapper = ldap_common.LdapWrapper(CONF.ldap.url, CONF.ldap.page_size, alias_dereferencing=deref) self.assertEqual(ldap.DEREF_SEARCHING, ldap_wrapper.conn.get_option(ldap.OPT_DEREF)) #FakeLDAP does not correctly process filters, so this test can only be run #against a live LDAP server def test_list_groups_for_user_filtered(self): domain = self._get_domain_fixture() test_groups = [] test_users = [] GROUP_COUNT = 3 USER_COUNT = 2 for x in range(0, USER_COUNT): new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} test_users.append(new_user) self.identity_api.create_user(new_user['id'], new_user) positive_user = test_users[0] negative_user = test_users[1] for x in range(0, USER_COUNT): group_refs = self.identity_api.list_groups_for_user( test_users[x]['id']) self.assertEqual(len(group_refs), 0) for x in range(0, GROUP_COUNT): new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) test_groups.append(new_group) group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), x) self.identity_api.add_user_to_group( positive_user['id'], new_group['id']) group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), x + 1) group_refs = self.identity_api.list_groups_for_user( negative_user['id']) self.assertEqual(len(group_refs), 0) self.config_fixture.config(group='ldap', group_filter='(dn=xx)') self.reload_backends(CONF.identity.default_domain_id) group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), 0) group_refs = self.identity_api.list_groups_for_user( negative_user['id']) self.assertEqual(len(group_refs), 0) self.config_fixture.config(group='ldap', group_filter='(objectclass=*)') self.reload_backends(CONF.identity.default_domain_id) group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), GROUP_COUNT) group_refs = self.identity_api.list_groups_for_user( negative_user['id']) self.assertEqual(len(group_refs), 0) def test_user_enable_attribute_mask(self): self.config_fixture.config( group='ldap', user_enabled_emulation=False, user_enabled_attribute='employeeType') super(LiveLDAPIdentity, self).test_user_enable_attribute_mask() def test_create_unicode_user_name(self): self.skipTest('Addressed by bug #1172106') def test_create_update_delete_unicode_project(self): self.skipTest('Addressed by bug #1172106') def test_create_project_case_sensitivity(self): # The attribute used for the live LDAP tests is case insensitive. def call_super(): super(LiveLDAPIdentity, self).\ test_create_project_case_sensitivity() self.assertRaises(exception.Conflict, call_super) def test_create_user_case_sensitivity(self): # The attribute used for the live LDAP tests is case insensitive. def call_super(): super(LiveLDAPIdentity, self).test_create_user_case_sensitivity() self.assertRaises(exception.Conflict, call_super) def test_project_update_missing_attrs_with_a_falsey_value(self): # The description attribute doesn't allow an empty value. def call_super(): super(LiveLDAPIdentity, self).\ test_project_update_missing_attrs_with_a_falsey_value() self.assertRaises(ldap.INVALID_SYNTAX, call_super) keystone-2014.1/keystone/tests/test_v2_controller.py0000664000175400017540000000635012323716267024023 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2014 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid from keystone.assignment import controllers from keystone import tests from keystone.tests import default_fixtures _ADMIN_CONTEXT = {'is_admin': True, 'query_string': {}} class TenantTestCase(tests.TestCase): """Tests for the V2 Tenant controller. These tests exercise :class:`keystone.assignment.controllers.Tenant`. """ def setUp(self): super(TenantTestCase, self).setUp() self.load_backends() self.load_fixtures(default_fixtures) self.tenant_controller = controllers.Tenant() self.role_controller = controllers.Role() def test_get_project_users_no_user(self): """get_project_users when user doesn't exist. When a user that's not known to `identity` has a role on a project, then `get_project_users` just skips that user. """ project_id = self.tenant_bar['id'] orig_project_users = self.tenant_controller.get_project_users( _ADMIN_CONTEXT, project_id) # Assign a role to a user that doesn't exist to the `bar` project. user_id = uuid.uuid4().hex self.role_controller.add_role_to_user( _ADMIN_CONTEXT, user_id, self.role_other['id'], project_id) new_project_users = self.tenant_controller.get_project_users( _ADMIN_CONTEXT, project_id) # The new user isn't included in the result, so no change. self.assertEqual(orig_project_users, new_project_users) def test_list_projects_default_domain(self): """Test that list projects only returns those in the default domain.""" domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} self.assignment_api.create_domain(domain['id'], domain) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project1['id'], project1) # Check the real total number of projects, we should have the above # plus those in the default features refs = self.assignment_api.list_projects() self.assertEqual(len(default_fixtures.TENANTS) + 1, len(refs)) # Now list all projects using the v2 API - we should only get # back those in the default features, since only those are in the # default domain. refs = self.tenant_controller.get_all_projects(_ADMIN_CONTEXT) self.assertEqual(len(default_fixtures.TENANTS), len(refs['tenants'])) for tenant in default_fixtures.TENANTS: tenant_copy = tenant.copy() tenant_copy.pop('domain_id') self.assertIn(tenant_copy, refs['tenants']) keystone-2014.1/keystone/tests/test_policy.py0000664000175400017540000002104412323716272022521 0ustar jenkinsjenkins00000000000000# Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import json import tempfile import six from six.moves.urllib import request as urlrequest from testtools import matchers from keystone import config from keystone import exception from keystone.openstack.common.fixture import moxstubout from keystone.openstack.common import policy as common_policy from keystone.policy.backends import rules from keystone import tests CONF = config.CONF class PolicyFileTestCase(tests.TestCase): def setUp(self): # self.tmpfilename should exist before setUp super is called # this is to ensure it is available for the config_fixture in # the config_overrides call. _unused, self.tmpfilename = tempfile.mkstemp() super(PolicyFileTestCase, self).setUp() rules.reset() self.addCleanup(rules.reset) self.target = {} def config_overrides(self): super(PolicyFileTestCase, self).config_overrides() self.config_fixture.config(policy_file=self.tmpfilename) def test_modified_policy_reloads(self): action = "example:test" empty_credentials = {} with open(self.tmpfilename, "w") as policyfile: policyfile.write("""{"example:test": []}""") rules.enforce(empty_credentials, action, self.target) with open(self.tmpfilename, "w") as policyfile: policyfile.write("""{"example:test": ["false:false"]}""") # NOTE(vish): reset stored policy cache so we don't have to sleep(1) rules._POLICY_CACHE = {} self.assertRaises(exception.ForbiddenAction, rules.enforce, empty_credentials, action, self.target) class PolicyTestCase(tests.TestCase): def setUp(self): super(PolicyTestCase, self).setUp() rules.reset() self.addCleanup(rules.reset) # NOTE(vish): preload rules to circumvent reloading from file rules.init() self.rules = { "true": [], "example:allowed": [], "example:denied": [["false:false"]], "example:get_http": [["http:http://www.example.com"]], "example:my_file": [["role:compute_admin"], ["project_id:%(project_id)s"]], "example:early_and_fail": [["false:false", "rule:true"]], "example:early_or_success": [["rule:true"], ["false:false"]], "example:lowercase_admin": [["role:admin"], ["role:sysadmin"]], "example:uppercase_admin": [["role:ADMIN"], ["role:sysadmin"]], } # NOTE(vish): then overload underlying policy engine self._set_rules() self.credentials = {} self.target = {} fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs def _set_rules(self): these_rules = common_policy.Rules( dict((k, common_policy.parse_rule(v)) for k, v in self.rules.items())) rules._ENFORCER.set_rules(these_rules) def test_enforce_nonexistent_action_throws(self): action = "example:noexist" self.assertRaises(exception.ForbiddenAction, rules.enforce, self.credentials, action, self.target) def test_enforce_bad_action_throws(self): action = "example:denied" self.assertRaises(exception.ForbiddenAction, rules.enforce, self.credentials, action, self.target) def test_enforce_good_action(self): action = "example:allowed" rules.enforce(self.credentials, action, self.target) def test_enforce_http_true(self): def fakeurlopen(url, post_data): return six.StringIO("True") self.stubs.Set(urlrequest, 'urlopen', fakeurlopen) action = "example:get_http" target = {} result = rules.enforce(self.credentials, action, target) self.assertTrue(result) def test_enforce_http_false(self): def fakeurlopen(url, post_data): return six.StringIO("False") self.stubs.Set(urlrequest, 'urlopen', fakeurlopen) action = "example:get_http" target = {} self.assertRaises(exception.ForbiddenAction, rules.enforce, self.credentials, action, target) def test_templatized_enforcement(self): target_mine = {'project_id': 'fake'} target_not_mine = {'project_id': 'another'} credentials = {'project_id': 'fake', 'roles': []} action = "example:my_file" rules.enforce(credentials, action, target_mine) self.assertRaises(exception.ForbiddenAction, rules.enforce, credentials, action, target_not_mine) def test_early_AND_enforcement(self): action = "example:early_and_fail" self.assertRaises(exception.ForbiddenAction, rules.enforce, self.credentials, action, self.target) def test_early_OR_enforcement(self): action = "example:early_or_success" rules.enforce(self.credentials, action, self.target) def test_ignore_case_role_check(self): lowercase_action = "example:lowercase_admin" uppercase_action = "example:uppercase_admin" # NOTE(dprince) we mix case in the Admin role here to ensure # case is ignored admin_credentials = {'roles': ['AdMiN']} rules.enforce(admin_credentials, lowercase_action, self.target) rules.enforce(admin_credentials, uppercase_action, self.target) class DefaultPolicyTestCase(tests.TestCase): def setUp(self): super(DefaultPolicyTestCase, self).setUp() rules.reset() self.addCleanup(rules.reset) rules.init() self.rules = { "default": [], "example:exist": [["false:false"]] } self._set_rules('default') self.credentials = {} # FIXME(gyee): latest Oslo policy Enforcer class reloads the rules in # its enforce() method even though rules has been initialized via # set_rules(). To make it easier to do our tests, we're going to # monkeypatch load_roles() so it does nothing. This seem like a bug in # Oslo policy as we shoudn't have to reload the rules if they have # already been set using set_rules(). self._old_load_rules = rules._ENFORCER.load_rules self.addCleanup(setattr, rules._ENFORCER, 'load_rules', self._old_load_rules) setattr(rules._ENFORCER, 'load_rules', lambda *args, **kwargs: None) def _set_rules(self, default_rule): these_rules = common_policy.Rules( dict((k, common_policy.parse_rule(v)) for k, v in self.rules.items()), default_rule) rules._ENFORCER.set_rules(these_rules) def test_policy_called(self): self.assertRaises(exception.ForbiddenAction, rules.enforce, self.credentials, "example:exist", {}) def test_not_found_policy_calls_default(self): rules.enforce(self.credentials, "example:noexist", {}) def test_default_not_found(self): new_default_rule = "default_noexist" # FIXME(gyee): need to overwrite the Enforcer's default_rule first # as it is recreating the rules with its own default_rule instead # of the default_rule passed in from set_rules(). I think this is a # bug in Oslo policy. rules._ENFORCER.default_rule = new_default_rule self._set_rules(new_default_rule) self.assertRaises(exception.ForbiddenAction, rules.enforce, self.credentials, "example:noexist", {}) class PolicyJsonTestCase(tests.TestCase): def _load_entries(self, filename): return set(json.load(file(filename))) def test_json_examples_have_matching_entries(self): policy_keys = self._load_entries(tests.dirs.etc('policy.json')) cloud_policy_keys = self._load_entries( tests.dirs.etc('policy.v3cloudsample.json')) diffs = set(policy_keys).difference(set(cloud_policy_keys)) self.assertThat(diffs, matchers.Equals(set())) keystone-2014.1/keystone/tests/test_sql_upgrade.py0000664000175400017540000032757212323716272023547 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """ To run these tests against a live database: 1. Modify the file ``keystone/tests/backend_sql.conf`` to use the connection for your live database 2. Set up a blank, live database 3. Run the tests using:: tox keystone.tests.test_sql_upgrade WARNING:: Your database will be wiped. Do not do this against a database with valuable data as all data will be lost. """ import copy import json import uuid from migrate.versioning import api as versioning_api import sqlalchemy import sqlalchemy.exc from keystone.assignment.backends import sql as assignment_sql from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.common import utils from keystone import config from keystone.contrib import federation from keystone import credential from keystone import exception from keystone.openstack.common.db import exception as db_exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.db.sqlalchemy import session as db_session from keystone import tests from keystone.tests import default_fixtures CONF = config.CONF DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id class SqlMigrateBase(tests.SQLDriverOverrides, tests.TestCase): def initialize_sql(self): self.metadata = sqlalchemy.MetaData() self.metadata.bind = self.engine def config_files(self): config_files = super(SqlMigrateBase, self).config_files() config_files.append(tests.dirs.tests_conf('backend_sql.conf')) return config_files def repo_package(self): return sql def setUp(self): super(SqlMigrateBase, self).setUp() self.config(self.config_files()) conn_str = CONF.database.connection if (conn_str.startswith('sqlite') and conn_str[10:] == tests.DEFAULT_TEST_DB_FILE): # Override the default with a DB that is specific to the migration # tests only if the DB Connection string is the same as the global # default. This is required so that no conflicts occur due to the # global default DB already being under migrate control. db_file = tests.dirs.tmp('keystone_migrate_test.db') self.config_fixture.config( group='database', connection='sqlite:///%s' % db_file) # create and share a single sqlalchemy engine for testing self.engine = sql.get_engine() self.Session = db_session.get_maker(self.engine, autocommit=False) self.initialize_sql() self.repo_path = migration_helpers.find_migrate_repo( self.repo_package()) self.schema = versioning_api.ControlledSchema.create( self.engine, self.repo_path, 0) # auto-detect the highest available schema version in the migrate_repo self.max_version = self.schema.repository.version().version def tearDown(self): sqlalchemy.orm.session.Session.close_all() table = sqlalchemy.Table("migrate_version", self.metadata, autoload=True) self.downgrade(0) table.drop(self.engine, checkfirst=True) sql.cleanup() super(SqlMigrateBase, self).tearDown() def select_table(self, name): table = sqlalchemy.Table(name, self.metadata, autoload=True) s = sqlalchemy.select([table]) return s def assertTableExists(self, table_name): try: self.select_table(table_name) except sqlalchemy.exc.NoSuchTableError: raise AssertionError('Table "%s" does not exist' % table_name) def assertTableDoesNotExist(self, table_name): """Asserts that a given table exists cannot be selected by name.""" # Switch to a different metadata otherwise you might still # detect renamed or dropped tables try: temp_metadata = sqlalchemy.MetaData() temp_metadata.bind = self.engine sqlalchemy.Table(table_name, temp_metadata, autoload=True) except sqlalchemy.exc.NoSuchTableError: pass else: raise AssertionError('Table "%s" already exists' % table_name) def upgrade(self, *args, **kwargs): self._migrate(*args, **kwargs) def downgrade(self, *args, **kwargs): self._migrate(*args, downgrade=True, **kwargs) def _migrate(self, version, repository=None, downgrade=False, current_schema=None): repository = repository or self.repo_path err = '' version = versioning_api._migrate_version(self.schema, version, not downgrade, err) if not current_schema: current_schema = self.schema changeset = current_schema.changeset(version) for ver, change in changeset: self.schema.runchange(ver, change, changeset.step) self.assertEqual(self.schema.version, version) def assertTableColumns(self, table_name, expected_cols): """Asserts that the table contains the expected set of columns.""" self.initialize_sql() table = self.select_table(table_name) actual_cols = [col.name for col in table.columns] self.assertEqual(expected_cols, actual_cols, '%s table' % table_name) class SqlUpgradeTests(SqlMigrateBase): def test_blank_db_to_start(self): self.assertTableDoesNotExist('user') def test_start_version_0(self): version = migration.db_version(sql.get_engine(), self.repo_path, 0) self.assertEqual(version, 0, "DB is not at version 0") def test_two_steps_forward_one_step_back(self): """You should be able to cleanly undo and re-apply all upgrades. Upgrades are run in the following order:: 0 -> 1 -> 0 -> 1 -> 2 -> 1 -> 2 -> 3 -> 2 -> 3 ... ^---------^ ^---------^ ^---------^ """ for x in range(1, self.max_version + 1): self.upgrade(x) self.downgrade(x - 1) self.upgrade(x) def test_upgrade_add_initial_tables(self): self.upgrade(1) self.assertTableColumns("user", ["id", "name", "extra"]) self.assertTableColumns("tenant", ["id", "name", "extra"]) self.assertTableColumns("role", ["id", "name"]) self.assertTableColumns("user_tenant_membership", ["user_id", "tenant_id"]) self.assertTableColumns("metadata", ["user_id", "tenant_id", "data"]) self.populate_user_table() def test_upgrade_add_policy(self): self.upgrade(5) self.assertTableDoesNotExist('policy') self.upgrade(6) self.assertTableExists('policy') self.assertTableColumns('policy', ['id', 'type', 'blob', 'extra']) def test_upgrade_normalize_identity(self): self.upgrade(8) self.populate_user_table() self.populate_tenant_table() self.upgrade(10) self.assertTableColumns("user", ["id", "name", "extra", "password", "enabled"]) self.assertTableColumns("tenant", ["id", "name", "extra", "description", "enabled"]) self.assertTableColumns("role", ["id", "name", "extra"]) self.assertTableColumns("user_tenant_membership", ["user_id", "tenant_id"]) self.assertTableColumns("metadata", ["user_id", "tenant_id", "data"]) session = self.Session() user_table = sqlalchemy.Table("user", self.metadata, autoload=True) a_user = session.query(user_table).filter("id='foo'").one() self.assertTrue(a_user.enabled) a_user = session.query(user_table).filter("id='badguy'").one() self.assertFalse(a_user.enabled) tenant_table = sqlalchemy.Table("tenant", self.metadata, autoload=True) a_tenant = session.query(tenant_table).filter("id='baz'").one() self.assertEqual(a_tenant.description, 'description') session.commit() session.close() def test_upgrade_user_tenant_membership_to_metadata(self): self.upgrade(16) self.assertTableColumns( 'user_project_membership', ['user_id', 'tenant_id']) user = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': 'default', 'extra': json.dumps({}), } project = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': 'default', 'extra': json.dumps({}), } metadata = { 'user_id': user['id'], 'tenant_id': project['id'], } session = self.Session() self.insert_dict(session, 'user', user) self.insert_dict(session, 'project', project) self.insert_dict(session, 'user_project_membership', metadata) self.upgrade(17) user_project_metadata_table = sqlalchemy.Table( 'user_project_metadata', self.metadata, autoload=True) result = session.query(user_project_metadata_table).one() self.assertEqual(result.user_id, user['id']) self.assertEqual(result.project_id, project['id']) self.assertEqual( json.loads(result.data), {'roles': [CONF.member_role_id]}) def test_normalized_enabled_states(self): self.upgrade(8) users = { 'bool_enabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': True})}, 'bool_disabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': False})}, 'str_enabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': 'True'})}, 'str_disabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': 'False'})}, 'int_enabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': 1})}, 'int_disabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': 0})}, 'null_enabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({'enabled': None})}, 'unset_enabled_user': { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'extra': json.dumps({})}} session = self.Session() for user in users.values(): self.insert_dict(session, 'user', user) session.commit() self.upgrade(10) user_table = sqlalchemy.Table('user', self.metadata, autoload=True) q = session.query(user_table, 'enabled') user = q.filter_by(id=users['bool_enabled_user']['id']).one() self.assertTrue(user.enabled) user = q.filter_by(id=users['bool_disabled_user']['id']).one() self.assertFalse(user.enabled) user = q.filter_by(id=users['str_enabled_user']['id']).one() self.assertTrue(user.enabled) user = q.filter_by(id=users['str_disabled_user']['id']).one() self.assertFalse(user.enabled) user = q.filter_by(id=users['int_enabled_user']['id']).one() self.assertTrue(user.enabled) user = q.filter_by(id=users['int_disabled_user']['id']).one() self.assertFalse(user.enabled) user = q.filter_by(id=users['null_enabled_user']['id']).one() self.assertTrue(user.enabled) user = q.filter_by(id=users['unset_enabled_user']['id']).one() self.assertTrue(user.enabled) def test_downgrade_10_to_8(self): self.upgrade(10) self.populate_user_table(with_pass_enab=True) self.populate_tenant_table(with_desc_enab=True) self.downgrade(8) self.assertTableColumns('user', ['id', 'name', 'extra']) self.assertTableColumns('tenant', ['id', 'name', 'extra']) session = self.Session() user_table = sqlalchemy.Table("user", self.metadata, autoload=True) a_user = session.query(user_table).filter("id='badguy'").one() self.assertEqual(a_user.name, default_fixtures.USERS[2]['name']) tenant_table = sqlalchemy.Table("tenant", self.metadata, autoload=True) a_tenant = session.query(tenant_table).filter("id='baz'").one() self.assertEqual(a_tenant.name, default_fixtures.TENANTS[1]['name']) session.commit() session.close() def test_upgrade_endpoints(self): self.upgrade(10) service_extra = { 'name': uuid.uuid4().hex, } service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'extra': json.dumps(service_extra), } endpoint_extra = { 'publicurl': uuid.uuid4().hex, 'internalurl': uuid.uuid4().hex, 'adminurl': uuid.uuid4().hex, } endpoint = { 'id': uuid.uuid4().hex, 'region': uuid.uuid4().hex, 'service_id': service['id'], 'extra': json.dumps(endpoint_extra), } session = self.Session() self.insert_dict(session, 'service', service) self.insert_dict(session, 'endpoint', endpoint) session.commit() session.close() self.upgrade(13) self.assertTableColumns( 'service', ['id', 'type', 'extra']) self.assertTableColumns( 'endpoint', ['id', 'legacy_endpoint_id', 'interface', 'region', 'service_id', 'url', 'extra']) endpoint_table = sqlalchemy.Table( 'endpoint', self.metadata, autoload=True) session = self.Session() self.assertEqual(session.query(endpoint_table).count(), 3) for interface in ['public', 'internal', 'admin']: q = session.query(endpoint_table) q = q.filter_by(legacy_endpoint_id=endpoint['id']) q = q.filter_by(interface=interface) ref = q.one() self.assertNotEqual(ref.id, endpoint['id']) self.assertEqual(ref.legacy_endpoint_id, endpoint['id']) self.assertEqual(ref.interface, interface) self.assertEqual(ref.region, endpoint['region']) self.assertEqual(ref.service_id, endpoint['service_id']) self.assertEqual(ref.url, endpoint_extra['%surl' % interface]) self.assertEqual(ref.extra, '{}') session.commit() session.close() def assertTenantTables(self): self.assertTableExists('tenant') self.assertTableExists('user_tenant_membership') self.assertTableDoesNotExist('project') self.assertTableDoesNotExist('user_project_membership') def assertProjectTables(self): self.assertTableExists('project') self.assertTableExists('user_project_membership') self.assertTableDoesNotExist('tenant') self.assertTableDoesNotExist('user_tenant_membership') def test_upgrade_tenant_to_project(self): self.upgrade(14) self.assertTenantTables() self.upgrade(15) self.assertProjectTables() def test_downgrade_project_to_tenant(self): # TODO(henry-nash): Debug why we need to re-load the tenant # or user_tenant_membership ahead of upgrading to project # in order for the assertProjectTables to work on sqlite # (MySQL is fine without it) self.upgrade(14) self.assertTenantTables() self.upgrade(15) self.assertProjectTables() self.downgrade(14) self.assertTenantTables() def test_upgrade_add_group_tables(self): self.upgrade(13) self.upgrade(14) self.assertTableExists('group') self.assertTableExists('group_project_metadata') self.assertTableExists('group_domain_metadata') self.assertTableExists('user_group_membership') def test_upgrade_14_to_16(self): self.upgrade(14) self.populate_user_table(with_pass_enab=True) self.populate_tenant_table(with_desc_enab=True) self.upgrade(16) self.assertTableColumns("user", ["id", "name", "extra", "password", "enabled", "domain_id"]) session = self.Session() user_table = sqlalchemy.Table("user", self.metadata, autoload=True) a_user = session.query(user_table).filter("id='foo'").one() self.assertTrue(a_user.enabled) self.assertEqual(a_user.domain_id, DEFAULT_DOMAIN_ID) a_user = session.query(user_table).filter("id='badguy'").one() self.assertEqual(a_user.name, default_fixtures.USERS[2]['name']) self.assertEqual(a_user.domain_id, DEFAULT_DOMAIN_ID) project_table = sqlalchemy.Table("project", self.metadata, autoload=True) a_project = session.query(project_table).filter("id='baz'").one() self.assertEqual(a_project.description, default_fixtures.TENANTS[1]['description']) self.assertEqual(a_project.domain_id, DEFAULT_DOMAIN_ID) session.commit() session.close() self.check_uniqueness_constraints() def test_downgrade_16_to_14(self): self.upgrade(16) self.populate_user_table(with_pass_enab_domain=True) self.populate_tenant_table(with_desc_enab_domain=True) self.downgrade(14) self.assertTableColumns("user", ["id", "name", "extra", "password", "enabled"]) session = self.Session() user_table = sqlalchemy.Table("user", self.metadata, autoload=True) a_user = session.query(user_table).filter("id='foo'").one() self.assertTrue(a_user.enabled) a_user = session.query(user_table).filter("id='badguy'").one() self.assertEqual(a_user.name, default_fixtures.USERS[2]['name']) tenant_table = sqlalchemy.Table("tenant", self.metadata, autoload=True) a_tenant = session.query(tenant_table).filter("id='baz'").one() self.assertEqual(a_tenant.description, default_fixtures.TENANTS[1]['description']) session.commit() session.close() def test_downgrade_remove_group_tables(self): self.upgrade(14) self.downgrade(13) self.assertTableDoesNotExist('group') self.assertTableDoesNotExist('group_project_metadata') self.assertTableDoesNotExist('group_domain_metadata') self.assertTableDoesNotExist('user_group_membership') def test_downgrade_endpoints(self): self.upgrade(13) service_extra = { 'name': uuid.uuid4().hex, } service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'extra': json.dumps(service_extra), } common_endpoint_attrs = { 'legacy_endpoint_id': uuid.uuid4().hex, 'region': uuid.uuid4().hex, 'service_id': service['id'], 'extra': json.dumps({}), } endpoints = { 'public': { 'id': uuid.uuid4().hex, 'interface': 'public', 'url': uuid.uuid4().hex, }, 'internal': { 'id': uuid.uuid4().hex, 'interface': 'internal', 'url': uuid.uuid4().hex, }, 'admin': { 'id': uuid.uuid4().hex, 'interface': 'admin', 'url': uuid.uuid4().hex, }, } session = self.Session() self.insert_dict(session, 'service', service) for endpoint in endpoints.values(): endpoint.update(common_endpoint_attrs) self.insert_dict(session, 'endpoint', endpoint) session.commit() session.close() self.downgrade(9) self.assertTableColumns( 'service', ['id', 'type', 'extra']) self.assertTableColumns( 'endpoint', ['id', 'region', 'service_id', 'extra']) endpoint_table = sqlalchemy.Table( 'endpoint', self.metadata, autoload=True) session = self.Session() self.assertEqual(session.query(endpoint_table).count(), 1) q = session.query(endpoint_table) q = q.filter_by(id=common_endpoint_attrs['legacy_endpoint_id']) ref = q.one() self.assertEqual(ref.id, common_endpoint_attrs['legacy_endpoint_id']) self.assertEqual(ref.region, endpoint['region']) self.assertEqual(ref.service_id, endpoint['service_id']) extra = json.loads(ref.extra) for interface in ['public', 'internal', 'admin']: expected_url = endpoints[interface]['url'] self.assertEqual(extra['%surl' % interface], expected_url) session.commit() session.close() def insert_dict(self, session, table_name, d, table=None): """Naively inserts key-value pairs into a table, given a dictionary.""" if table is None: this_table = sqlalchemy.Table(table_name, self.metadata, autoload=True) else: this_table = table insert = this_table.insert() insert.execute(d) session.commit() def test_upgrade_31_to_32(self): self.upgrade(32) user_table = self.select_table("user") self.assertEqual(user_table.c.name.type.length, 255) def test_downgrade_32_to_31(self): self.upgrade(32) session = self.Session() # NOTE(aloga): we need a different metadata object user_table = sqlalchemy.Table('user', sqlalchemy.MetaData(), autoload=True, autoload_with=self.engine) user_id = uuid.uuid4().hex ins = user_table.insert().values( {'id': user_id, 'name': 'a' * 255, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID, 'extra': '{}'}) session.execute(ins) session.commit() self.downgrade(31) # Check that username has been truncated q = session.query(user_table.c.name) q = q.filter(user_table.c.id == user_id) r = q.one() user_name = r[0] self.assertEqual(len(user_name), 64) user_table = self.select_table("user") self.assertEqual(user_table.c.name.type.length, 64) def test_downgrade_to_0(self): self.upgrade(self.max_version) if self.engine.name == 'mysql': self._mysql_check_all_tables_innodb() self.downgrade(0) for table_name in ["user", "token", "role", "user_tenant_membership", "metadata"]: self.assertTableDoesNotExist(table_name) def test_upgrade_add_domain_tables(self): self.upgrade(6) self.assertTableDoesNotExist('credential') self.assertTableDoesNotExist('domain') self.assertTableDoesNotExist('user_domain_metadata') self.upgrade(7) self.assertTableExists('credential') self.assertTableColumns('credential', ['id', 'user_id', 'project_id', 'blob', 'type', 'extra']) self.assertTableExists('domain') self.assertTableColumns('domain', ['id', 'name', 'enabled', 'extra']) self.assertTableExists('user_domain_metadata') self.assertTableColumns('user_domain_metadata', ['user_id', 'domain_id', 'data']) def test_metadata_table_migration(self): # Scaffolding session = self.Session() self.upgrade(16) domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True) user_table = sqlalchemy.Table('user', self.metadata, autoload=True) role_table = sqlalchemy.Table('role', self.metadata, autoload=True) project_table = sqlalchemy.Table( 'project', self.metadata, autoload=True) metadata_table = sqlalchemy.Table( 'metadata', self.metadata, autoload=True) # Create a Domain domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} session.execute(domain_table.insert().values(domain)) # Create a Project project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'extra': "{}"} session.execute(project_table.insert().values(project)) # Create another Project project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'extra': "{}"} session.execute(project_table.insert().values(project2)) # Create a User user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'password': uuid.uuid4().hex, 'enabled': True, 'extra': json.dumps({})} session.execute(user_table.insert().values(user)) # Create a Role role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} session.execute(role_table.insert().values(role)) # And another role role2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} session.execute(role_table.insert().values(role2)) # Grant Role to User role_grant = {'user_id': user['id'], 'tenant_id': project['id'], 'data': json.dumps({"roles": [role['id']]})} session.execute(metadata_table.insert().values(role_grant)) role_grant = {'user_id': user['id'], 'tenant_id': project2['id'], 'data': json.dumps({"roles": [role2['id']]})} session.execute(metadata_table.insert().values(role_grant)) # Create another user to test the case where member_role_id is already # assigned. user2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'password': uuid.uuid4().hex, 'enabled': True, 'extra': json.dumps({})} session.execute(user_table.insert().values(user2)) # Grant CONF.member_role_id to User2 role_grant = {'user_id': user2['id'], 'tenant_id': project['id'], 'data': json.dumps({"roles": [CONF.member_role_id]})} session.execute(metadata_table.insert().values(role_grant)) session.commit() self.upgrade(17) user_project_metadata_table = sqlalchemy.Table( 'user_project_metadata', self.metadata, autoload=True) s = sqlalchemy.select([metadata_table.c.data]).where( (metadata_table.c.user_id == user['id']) & (metadata_table.c.tenant_id == project['id'])) r = session.execute(s) test_project1 = json.loads(r.fetchone()['data']) self.assertEqual(len(test_project1['roles']), 1) self.assertIn(role['id'], test_project1['roles']) # Test user in project2 has role2 s = sqlalchemy.select([metadata_table.c.data]).where( (metadata_table.c.user_id == user['id']) & (metadata_table.c.tenant_id == project2['id'])) r = session.execute(s) test_project2 = json.loads(r.fetchone()['data']) self.assertEqual(len(test_project2['roles']), 1) self.assertIn(role2['id'], test_project2['roles']) # Test for user in project has role in user_project_metadata # Migration 17 does not properly migrate this data, so this should # be None. s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project['id'])) r = session.execute(s) self.assertIsNone(r.fetchone()) # Create a conflicting user-project in user_project_metadata with # a different role data = json.dumps({"roles": [role2['id']]}) role_grant = {'user_id': user['id'], 'project_id': project['id'], 'data': data} cmd = user_project_metadata_table.insert().values(role_grant) self.engine.execute(cmd) # Create another conflicting user-project for User2 data = json.dumps({"roles": [role2['id']]}) role_grant = {'user_id': user2['id'], 'project_id': project['id'], 'data': data} cmd = user_project_metadata_table.insert().values(role_grant) self.engine.execute(cmd) # End Scaffolding session.commit() # Migrate to 20 self.upgrade(20) # The user-project pairs should have all roles from the previous # metadata table in addition to any roles currently in # user_project_metadata s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project['id'])) r = session.execute(s) role_ids = json.loads(r.fetchone()['data'])['roles'] self.assertEqual(len(role_ids), 3) self.assertIn(CONF.member_role_id, role_ids) self.assertIn(role['id'], role_ids) self.assertIn(role2['id'], role_ids) # pairs that only existed in old metadata table should be in # user_project_metadata s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project2['id'])) r = session.execute(s) role_ids = json.loads(r.fetchone()['data'])['roles'] self.assertEqual(len(role_ids), 2) self.assertIn(CONF.member_role_id, role_ids) self.assertIn(role2['id'], role_ids) self.assertTableDoesNotExist('metadata') def test_upgrade_default_roles(self): def count_member_roles(): session = self.Session() role_table = sqlalchemy.Table("role", self.metadata, autoload=True) return session.query(role_table).filter_by( name=config.CONF.member_role_name).count() self.upgrade(16) self.assertEqual(0, count_member_roles()) self.upgrade(17) self.assertEqual(1, count_member_roles()) self.downgrade(16) self.assertEqual(0, count_member_roles()) def check_uniqueness_constraints(self): # Check uniqueness constraints for User & Project tables are # correct following schema modification. The Group table's # schema is never modified, so we don't bother to check that. domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} cmd = domain_table.insert().values(domain1) self.engine.execute(cmd) cmd = domain_table.insert().values(domain2) self.engine.execute(cmd) # First, the User table. this_table = sqlalchemy.Table('user', self.metadata, autoload=True) user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True, 'extra': json.dumps({})} cmd = this_table.insert().values(user) self.engine.execute(cmd) # now insert a user with the same name into a different # domain - which should work. user['id'] = uuid.uuid4().hex user['domain_id'] = domain2['id'] cmd = this_table.insert().values(user) self.engine.execute(cmd) # TODO(henry-nash): For now, as part of clean-up we delete one of these # users. Although not part of this test, unless we do so the # downgrade(16->15) that is part of teardown with fail due to having # two uses with clashing name as we try to revert to a single global # name space. This limitation is raised as Bug #1125046 and the delete # could be removed depending on how that bug is resolved. cmd = this_table.delete().where(this_table.c.id == user['id']) self.engine.execute(cmd) # Now, the Project table. this_table = sqlalchemy.Table('project', self.metadata, autoload=True) project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'description': uuid.uuid4().hex, 'enabled': True, 'extra': json.dumps({})} cmd = this_table.insert().values(project) self.engine.execute(cmd) # now insert a project with the same name into a different # domain - which should work. project['id'] = uuid.uuid4().hex project['domain_id'] = domain2['id'] cmd = this_table.insert().values(project) self.engine.execute(cmd) # TODO(henry-nash): For now, we delete one of the projects for the same # reason as we delete one of the users (Bug #1125046). This delete # could be removed depending on that bug resolution. cmd = this_table.delete().where(this_table.c.id == project['id']) self.engine.execute(cmd) def test_upgrade_trusts(self): self.assertEqual(self.schema.version, 0, "DB is at version 0") self.upgrade(20) self.assertTableColumns("token", ["id", "expires", "extra", "valid"]) self.upgrade(21) self.assertTableColumns("trust", ["id", "trustor_user_id", "trustee_user_id", "project_id", "impersonation", "deleted_at", "expires_at", "extra"]) self.assertTableColumns("trust_role", ["trust_id", "role_id"]) self.assertTableColumns("token", ["id", "expires", "extra", "valid", "trust_id", "user_id"]) def test_fixup_role(self): def count_role(): session = self.Session() self.initialize_sql() role_table = sqlalchemy.Table("role", self.metadata, autoload=True) return session.query(role_table).filter_by(extra=None).count() session = self.Session() self.assertEqual(self.schema.version, 0, "DB is at version 0") self.upgrade(1) self.insert_dict(session, "role", {"id": "test", "name": "test"}) self.upgrade(18) self.insert_dict(session, "role", {"id": "test2", "name": "test2", "extra": None}) self.assertEqual(count_role(), 2) self.upgrade(19) self.assertEqual(count_role(), 0) def test_legacy_endpoint_id(self): session = self.Session() self.upgrade(21) service = { 'id': uuid.uuid4().hex, 'name': 'keystone', 'type': 'identity'} self.insert_dict(session, 'service', service) legacy_endpoint_id = uuid.uuid4().hex endpoint = { 'id': uuid.uuid4().hex, 'service_id': service['id'], 'interface': uuid.uuid4().hex[:8], 'url': uuid.uuid4().hex, 'extra': json.dumps({ 'legacy_endpoint_id': legacy_endpoint_id})} self.insert_dict(session, 'endpoint', endpoint) session.commit() self.upgrade(22) endpoint_table = sqlalchemy.Table( 'endpoint', self.metadata, autoload=True) self.assertEqual(session.query(endpoint_table).count(), 1) ref = session.query(endpoint_table).one() self.assertEqual(ref.id, endpoint['id'], ref) self.assertEqual(ref.service_id, endpoint['service_id']) self.assertEqual(ref.interface, endpoint['interface']) self.assertEqual(ref.url, endpoint['url']) self.assertEqual(ref.legacy_endpoint_id, legacy_endpoint_id) self.assertEqual(ref.extra, '{}') def test_group_project_FK_fixup(self): # To create test data we must start before we broke in the # group_project_metadata table in 015. self.upgrade(14) session = self.Session() domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True) group_table = sqlalchemy.Table('group', self.metadata, autoload=True) tenant_table = sqlalchemy.Table('tenant', self.metadata, autoload=True) role_table = sqlalchemy.Table('role', self.metadata, autoload=True) group_project_metadata_table = sqlalchemy.Table( 'group_project_metadata', self.metadata, autoload=True) # Create a Domain domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} session.execute(domain_table.insert().values(domain)) # Create two Tenants tenant = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'extra': "{}"} session.execute(tenant_table.insert().values(tenant)) tenant1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'extra': "{}"} session.execute(tenant_table.insert().values(tenant1)) # Create a Group group = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'extra': json.dumps({})} session.execute(group_table.insert().values(group)) # Create roles role_list = [] for _ in range(2): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} session.execute(role_table.insert().values(role)) role_list.append(role) # Grant Role to User on Project role_grant = {'group_id': group['id'], 'project_id': tenant['id'], 'data': json.dumps({'roles': [role_list[0]['id']]})} session.execute( group_project_metadata_table.insert().values(role_grant)) role_grant = {'group_id': group['id'], 'project_id': tenant1['id'], 'data': json.dumps({'roles': [role_list[1]['id']]})} session.execute( group_project_metadata_table.insert().values(role_grant)) session.commit() # Now upgrade and fix up the FKs self.upgrade(28) self.assertTableExists('group_project_metadata') self.assertTableExists('project') self.assertTableDoesNotExist('tenant') s = sqlalchemy.select([group_project_metadata_table.c.data]).where( (group_project_metadata_table.c.group_id == group['id']) & (group_project_metadata_table.c.project_id == tenant['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[0]['id'], data['roles']) s = sqlalchemy.select([group_project_metadata_table.c.data]).where( (group_project_metadata_table.c.group_id == group['id']) & (group_project_metadata_table.c.project_id == tenant1['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[1]['id'], data['roles']) self.downgrade(27) self.assertTableExists('group_project_metadata') self.assertTableExists('project') self.assertTableDoesNotExist('tenant') def test_assignment_metadata_migration(self): self.upgrade(28) # Scaffolding session = self.Session() domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True) user_table = sqlalchemy.Table('user', self.metadata, autoload=True) group_table = sqlalchemy.Table('group', self.metadata, autoload=True) role_table = sqlalchemy.Table('role', self.metadata, autoload=True) project_table = sqlalchemy.Table( 'project', self.metadata, autoload=True) user_project_metadata_table = sqlalchemy.Table( 'user_project_metadata', self.metadata, autoload=True) user_domain_metadata_table = sqlalchemy.Table( 'user_domain_metadata', self.metadata, autoload=True) group_project_metadata_table = sqlalchemy.Table( 'group_project_metadata', self.metadata, autoload=True) group_domain_metadata_table = sqlalchemy.Table( 'group_domain_metadata', self.metadata, autoload=True) # Create a Domain domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} session.execute(domain_table.insert().values(domain)) # Create anther Domain domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} session.execute(domain_table.insert().values(domain2)) # Create a Project project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'extra': "{}"} session.execute(project_table.insert().values(project)) # Create another Project project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'extra': "{}"} session.execute(project_table.insert().values(project2)) # Create a User user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'password': uuid.uuid4().hex, 'enabled': True, 'extra': json.dumps({})} session.execute(user_table.insert().values(user)) # Create a Group group = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id'], 'extra': json.dumps({})} session.execute(group_table.insert().values(group)) # Create roles role_list = [] for _ in range(7): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} session.execute(role_table.insert().values(role)) role_list.append(role) # Grant Role to User on Project role_grant = {'user_id': user['id'], 'project_id': project['id'], 'data': json.dumps({'roles': [role_list[0]['id']]})} session.execute( user_project_metadata_table.insert().values(role_grant)) role_grant = {'user_id': user['id'], 'project_id': project2['id'], 'data': json.dumps({'roles': [role_list[1]['id']]})} session.execute( user_project_metadata_table.insert().values(role_grant)) # Grant Role to Group on different Project role_grant = {'group_id': group['id'], 'project_id': project2['id'], 'data': json.dumps({'roles': [role_list[2]['id']]})} session.execute( group_project_metadata_table.insert().values(role_grant)) # Grant Role to User on Domain role_grant = {'user_id': user['id'], 'domain_id': domain['id'], 'data': json.dumps({'roles': [role_list[3]['id']]})} session.execute(user_domain_metadata_table.insert().values(role_grant)) # Grant Role to Group on Domain role_grant = {'group_id': group['id'], 'domain_id': domain['id'], 'data': json.dumps( {'roles': [role_list[4]['id']], 'other': 'somedata'})} session.execute( group_domain_metadata_table.insert().values(role_grant)) session.commit() self.upgrade(29) s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': role_list[0]['id']}, data['roles']) s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project2['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': role_list[1]['id']}, data['roles']) s = sqlalchemy.select([group_project_metadata_table.c.data]).where( (group_project_metadata_table.c.group_id == group['id']) & (group_project_metadata_table.c.project_id == project2['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': role_list[2]['id']}, data['roles']) s = sqlalchemy.select([user_domain_metadata_table.c.data]).where( (user_domain_metadata_table.c.user_id == user['id']) & (user_domain_metadata_table.c.domain_id == domain['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': role_list[3]['id']}, data['roles']) s = sqlalchemy.select([group_domain_metadata_table.c.data]).where( (group_domain_metadata_table.c.group_id == group['id']) & (group_domain_metadata_table.c.domain_id == domain['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': role_list[4]['id']}, data['roles']) self.assertIn('other', data) # Now add an entry that has one regular and one inherited role role_grant = {'user_id': user['id'], 'domain_id': domain2['id'], 'data': json.dumps( {'roles': [{'id': role_list[5]['id']}, {'id': role_list[6]['id'], 'inherited_to': 'projects'}]})} session.execute(user_domain_metadata_table.insert().values(role_grant)) session.commit() self.downgrade(28) s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[0]['id'], data['roles']) s = sqlalchemy.select([user_project_metadata_table.c.data]).where( (user_project_metadata_table.c.user_id == user['id']) & (user_project_metadata_table.c.project_id == project2['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[1]['id'], data['roles']) s = sqlalchemy.select([group_project_metadata_table.c.data]).where( (group_project_metadata_table.c.group_id == group['id']) & (group_project_metadata_table.c.project_id == project2['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[2]['id'], data['roles']) s = sqlalchemy.select([user_domain_metadata_table.c.data]).where( (user_domain_metadata_table.c.user_id == user['id']) & (user_domain_metadata_table.c.domain_id == domain['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[3]['id'], data['roles']) s = sqlalchemy.select([group_domain_metadata_table.c.data]).where( (group_domain_metadata_table.c.group_id == group['id']) & (group_domain_metadata_table.c.domain_id == domain['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[4]['id'], data['roles']) self.assertIn('other', data) # For user-domain2, where we had one regular and one inherited role, # only the direct role should remain, the inherited role should # have been deleted during the downgrade s = sqlalchemy.select([user_domain_metadata_table.c.data]).where( (user_domain_metadata_table.c.user_id == user['id']) & (user_domain_metadata_table.c.domain_id == domain2['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn(role_list[5]['id'], data['roles']) def test_drop_credential_constraint(self): ec2_credential = { 'id': '100', 'user_id': 'foo', 'project_id': 'bar', 'type': 'ec2', 'blob': json.dumps({ "access": "12345", "secret": "12345" }) } user = { 'id': 'foo', 'name': 'FOO', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'enabled': True}) } tenant = { 'id': 'bar', 'name': 'BAR', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } session = self.Session() self.upgrade(7) self.insert_dict(session, 'user', user) self.insert_dict(session, 'tenant', tenant) self.insert_dict(session, 'credential', ec2_credential) session.commit() self.upgrade(30) cred_table = sqlalchemy.Table('credential', self.metadata, autoload=True) cred = session.query(cred_table).filter("id='100'").one() self.assertEqual(cred.user_id, ec2_credential['user_id']) def test_drop_credential_indexes(self): self.upgrade(31) table = sqlalchemy.Table('credential', self.metadata, autoload=True) self.assertEqual(len(table.indexes), 0) def test_downgrade_30(self): self.upgrade(31) self.downgrade(30) table = sqlalchemy.Table('credential', self.metadata, autoload=True) index_data = [(idx.name, idx.columns.keys()) for idx in table.indexes] if self.engine.name == 'mysql': self.assertIn(('user_id', ['user_id']), index_data) self.assertIn(('credential_project_id_fkey', ['project_id']), index_data) else: self.assertEqual(len(index_data), 0) def test_revoked_token_index(self): self.upgrade(35) table = sqlalchemy.Table('token', self.metadata, autoload=True) index_data = [(idx.name, idx.columns.keys()) for idx in table.indexes] self.assertIn(('ix_token_expires_valid', ['expires', 'valid']), index_data) def test_dropped_valid_index(self): self.upgrade(36) table = sqlalchemy.Table('token', self.metadata, autoload=True) index_data = [(idx.name, idx.columns.keys()) for idx in table.indexes] self.assertNotIn(('ix_token_valid', ['valid']), index_data) def test_migrate_ec2_credential(self): user = { 'id': 'foo', 'name': 'FOO', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'enabled': True}) } project = { 'id': 'bar', 'name': 'BAR', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } ec2_credential = { 'access': uuid.uuid4().hex, 'secret': uuid.uuid4().hex, 'user_id': user['id'], 'tenant_id': project['id'], } session = self.Session() self.upgrade(7) self.insert_dict(session, 'ec2_credential', ec2_credential) self.insert_dict(session, 'user', user) self.insert_dict(session, 'tenant', project) self.upgrade(33) self.assertTableDoesNotExist('ec2_credential') cred_table = sqlalchemy.Table('credential', self.metadata, autoload=True) expected_credential_id = utils.hash_access_key( ec2_credential['access']) cred = session.query(cred_table).filter_by( id=expected_credential_id).one() self.assertEqual(cred.user_id, ec2_credential['user_id']) self.assertEqual(cred.project_id, ec2_credential['tenant_id']) # test list credential using credential manager. credential_api = credential.Manager() self.assertNotEmpty(credential_api. list_credentials( user_id=ec2_credential['user_id'])) self.downgrade(32) session.commit() self.assertTableExists('ec2_credential') ec2_cred_table = sqlalchemy.Table('ec2_credential', self.metadata, autoload=True) ec2_cred = session.query(ec2_cred_table).filter_by( access=ec2_credential['access']).one() self.assertEqual(ec2_cred.user_id, ec2_credential['user_id']) def test_migrate_ec2_credential_with_conflict_project(self): user = { 'id': 'foo', 'name': 'FOO', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'enabled': True}) } project_1 = { 'id': 'bar', 'name': 'BAR', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } project_2 = { 'id': 'baz', 'name': 'BAZ', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } ec2_credential = { 'access': uuid.uuid4().hex, 'secret': uuid.uuid4().hex, 'user_id': user['id'], 'tenant_id': project_1['id'], } blob = {'access': ec2_credential['access'], 'secret': ec2_credential['secret']} v3_credential = { 'id': utils.hash_access_key(ec2_credential['access']), 'user_id': user['id'], # set the project id to simulate a conflict 'project_id': project_2['id'], 'blob': json.dumps(blob), 'type': 'ec2', 'extra': json.dumps({}) } session = self.Session() self.upgrade(7) self.insert_dict(session, 'ec2_credential', ec2_credential) self.insert_dict(session, 'user', user) self.insert_dict(session, 'tenant', project_1) self.insert_dict(session, 'tenant', project_2) self.upgrade(32) self.insert_dict(session, 'credential', v3_credential) self.assertRaises(exception.Conflict, self.upgrade, 33) def test_migrate_ec2_credential_with_conflict_secret(self): user = { 'id': 'foo', 'name': 'FOO', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'enabled': True}) } project_1 = { 'id': 'bar', 'name': 'BAR', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } project_2 = { 'id': 'baz', 'name': 'BAZ', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } ec2_credential = { 'access': uuid.uuid4().hex, 'secret': uuid.uuid4().hex, 'user_id': user['id'], 'tenant_id': project_1['id'], } blob = {'access': ec2_credential['access'], 'secret': 'different secret'} v3_cred_different_secret = { 'id': utils.hash_access_key(ec2_credential['access']), 'user_id': user['id'], 'project_id': project_1['id'], 'blob': json.dumps(blob), 'type': 'ec2', 'extra': json.dumps({}) } session = self.Session() self.upgrade(7) self.insert_dict(session, 'ec2_credential', ec2_credential) self.insert_dict(session, 'user', user) self.insert_dict(session, 'tenant', project_1) self.insert_dict(session, 'tenant', project_2) self.upgrade(32) self.insert_dict(session, 'credential', v3_cred_different_secret) self.assertRaises(exception.Conflict, self.upgrade, 33) def test_migrate_ec2_credential_with_invalid_blob(self): user = { 'id': 'foo', 'name': 'FOO', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'enabled': True}) } project_1 = { 'id': 'bar', 'name': 'BAR', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } project_2 = { 'id': 'baz', 'name': 'BAZ', 'description': 'description', 'enabled': True, 'extra': json.dumps({'enabled': True}) } ec2_credential = { 'access': uuid.uuid4().hex, 'secret': uuid.uuid4().hex, 'user_id': user['id'], 'tenant_id': project_1['id'], } blob = '{"abc":"def"d}' v3_cred_invalid_blob = { 'id': utils.hash_access_key(ec2_credential['access']), 'user_id': user['id'], 'project_id': project_1['id'], 'blob': json.dumps(blob), 'type': 'ec2', 'extra': json.dumps({}) } session = self.Session() self.upgrade(7) self.insert_dict(session, 'ec2_credential', ec2_credential) self.insert_dict(session, 'user', user) self.insert_dict(session, 'tenant', project_1) self.insert_dict(session, 'tenant', project_2) self.upgrade(32) self.insert_dict(session, 'credential', v3_cred_invalid_blob) self.assertRaises(exception.ValidationError, self.upgrade, 33) def test_migrate_add_default_project_id_column_upgrade(self): user1 = { 'id': 'foo1', 'name': 'FOO1', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'tenantId': 'bar'}), 'domain_id': DEFAULT_DOMAIN_ID } user2 = { 'id': 'foo2', 'name': 'FOO2', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'tenant_id': 'bar'}), 'domain_id': DEFAULT_DOMAIN_ID } user3 = { 'id': 'foo3', 'name': 'FOO3', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'default_project_id': 'bar'}), 'domain_id': DEFAULT_DOMAIN_ID } user4 = { 'id': 'foo4', 'name': 'FOO4', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({'tenantId': 'baz', 'default_project_id': 'bar'}), 'domain_id': DEFAULT_DOMAIN_ID } session = self.Session() self.upgrade(33) self.insert_dict(session, 'user', user1) self.insert_dict(session, 'user', user2) self.insert_dict(session, 'user', user3) self.insert_dict(session, 'user', user4) self.assertTableColumns('user', ['id', 'name', 'extra', 'password', 'enabled', 'domain_id']) session.commit() session.close() self.upgrade(34) session = self.Session() self.assertTableColumns('user', ['id', 'name', 'extra', 'password', 'enabled', 'domain_id', 'default_project_id']) user_table = sqlalchemy.Table('user', self.metadata, autoload=True) updated_user1 = session.query(user_table).filter_by(id='foo1').one() old_json_data = json.loads(user1['extra']) new_json_data = json.loads(updated_user1.extra) self.assertNotIn('tenantId', new_json_data) self.assertEqual(old_json_data['tenantId'], updated_user1.default_project_id) updated_user2 = session.query(user_table).filter_by(id='foo2').one() old_json_data = json.loads(user2['extra']) new_json_data = json.loads(updated_user2.extra) self.assertNotIn('tenant_id', new_json_data) self.assertEqual(old_json_data['tenant_id'], updated_user2.default_project_id) updated_user3 = session.query(user_table).filter_by(id='foo3').one() old_json_data = json.loads(user3['extra']) new_json_data = json.loads(updated_user3.extra) self.assertNotIn('default_project_id', new_json_data) self.assertEqual(old_json_data['default_project_id'], updated_user3.default_project_id) updated_user4 = session.query(user_table).filter_by(id='foo4').one() old_json_data = json.loads(user4['extra']) new_json_data = json.loads(updated_user4.extra) self.assertNotIn('default_project_id', new_json_data) self.assertNotIn('tenantId', new_json_data) self.assertEqual(old_json_data['default_project_id'], updated_user4.default_project_id) def test_migrate_add_default_project_id_column_downgrade(self): user1 = { 'id': 'foo1', 'name': 'FOO1', 'password': 'foo2', 'enabled': True, 'email': 'foo@bar.com', 'extra': json.dumps({}), 'default_project_id': 'bar', 'domain_id': DEFAULT_DOMAIN_ID } self.upgrade(34) session = self.Session() self.insert_dict(session, 'user', user1) self.assertTableColumns('user', ['id', 'name', 'extra', 'password', 'enabled', 'domain_id', 'default_project_id']) session.commit() session.close() self.downgrade(33) session = self.Session() self.assertTableColumns('user', ['id', 'name', 'extra', 'password', 'enabled', 'domain_id']) user_table = sqlalchemy.Table('user', self.metadata, autoload=True) updated_user1 = session.query(user_table).filter_by(id='foo1').one() new_json_data = json.loads(updated_user1.extra) self.assertIn('tenantId', new_json_data) self.assertIn('default_project_id', new_json_data) self.assertEqual(user1['default_project_id'], new_json_data['tenantId']) self.assertEqual(user1['default_project_id'], new_json_data['default_project_id']) self.assertEqual(user1['default_project_id'], new_json_data['tenant_id']) def test_region_migration(self): self.upgrade(36) self.assertTableDoesNotExist('region') self.upgrade(37) self.assertTableExists('region') self.downgrade(36) self.assertTableDoesNotExist('region') def test_assignment_table_migration(self): def create_base_data(session): domain_table = sqlalchemy.Table('domain', self.metadata, autoload=True) user_table = sqlalchemy.Table('user', self.metadata, autoload=True) group_table = sqlalchemy.Table('group', self.metadata, autoload=True) role_table = sqlalchemy.Table('role', self.metadata, autoload=True) project_table = sqlalchemy.Table( 'project', self.metadata, autoload=True) base_data = {} # Create a Domain base_data['domain'] = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} session.execute(domain_table.insert().values(base_data['domain'])) # Create another Domain base_data['domain2'] = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} session.execute(domain_table.insert().values(base_data['domain2'])) # Create a Project base_data['project'] = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': base_data['domain']['id'], 'extra': "{}"} session.execute( project_table.insert().values(base_data['project'])) # Create another Project base_data['project2'] = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': base_data['domain']['id'], 'extra': "{}"} session.execute( project_table.insert().values(base_data['project2'])) # Create a User base_data['user'] = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': base_data['domain']['id'], 'password': uuid.uuid4().hex, 'enabled': True, 'extra': "{}"} session.execute(user_table.insert().values(base_data['user'])) # Create a Group base_data['group'] = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': base_data['domain']['id'], 'extra': "{}"} session.execute(group_table.insert().values(base_data['group'])) # Create roles base_data['roles'] = [] for _ in range(9): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} session.execute(role_table.insert().values(role)) base_data['roles'].append(role) return base_data def populate_grants(session, base_data): user_project_table = sqlalchemy.Table( 'user_project_metadata', self.metadata, autoload=True) user_domain_table = sqlalchemy.Table( 'user_domain_metadata', self.metadata, autoload=True) group_project_table = sqlalchemy.Table( 'group_project_metadata', self.metadata, autoload=True) group_domain_table = sqlalchemy.Table( 'group_domain_metadata', self.metadata, autoload=True) # Grant a role to user on project grant = {'user_id': base_data['user']['id'], 'project_id': base_data['project']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][0]['id']}]})} session.execute(user_project_table.insert().values(grant)) # Grant two roles to user on project2 grant = {'user_id': base_data['user']['id'], 'project_id': base_data['project2']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][1]['id']}, {'id': base_data['roles'][2]['id']}]})} session.execute(user_project_table.insert().values(grant)) # Grant role to group on project grant = {'group_id': base_data['group']['id'], 'project_id': base_data['project']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][3]['id']}]})} session.execute(group_project_table.insert().values(grant)) # Grant two roles to group on project2 grant = {'group_id': base_data['group']['id'], 'project_id': base_data['project2']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][4]['id']}, {'id': base_data['roles'][5]['id']}]})} session.execute(group_project_table.insert().values(grant)) # Grant two roles to group on domain, one inherited, one not grant = {'group_id': base_data['group']['id'], 'domain_id': base_data['domain']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][6]['id']}, {'id': base_data['roles'][7]['id'], 'inherited_to': 'projects'}]})} session.execute(group_domain_table.insert().values(grant)) # Grant inherited role to user on domain grant = {'user_id': base_data['user']['id'], 'domain_id': base_data['domain']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][8]['id'], 'inherited_to': 'projects'}]})} session.execute(user_domain_table.insert().values(grant)) # Grant two non-inherited roles to user on domain2, using roles # that are also assigned to other actors/targets grant = {'user_id': base_data['user']['id'], 'domain_id': base_data['domain2']['id'], 'data': json.dumps( {'roles': [{'id': base_data['roles'][6]['id']}, {'id': base_data['roles'][7]['id']}]})} session.execute(user_domain_table.insert().values(grant)) session.commit() def check_grants(session, base_data): user_project_table = sqlalchemy.Table( 'user_project_metadata', self.metadata, autoload=True) user_domain_table = sqlalchemy.Table( 'user_domain_metadata', self.metadata, autoload=True) group_project_table = sqlalchemy.Table( 'group_project_metadata', self.metadata, autoload=True) group_domain_table = sqlalchemy.Table( 'group_domain_metadata', self.metadata, autoload=True) s = sqlalchemy.select([user_project_table.c.data]).where( (user_project_table.c.user_id == base_data['user']['id']) & (user_project_table.c.project_id == base_data['project']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': base_data['roles'][0]['id']}, data['roles']) s = sqlalchemy.select([user_project_table.c.data]).where( (user_project_table.c.user_id == base_data['user']['id']) & (user_project_table.c.project_id == base_data['project2']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 2) self.assertIn({'id': base_data['roles'][1]['id']}, data['roles']) self.assertIn({'id': base_data['roles'][2]['id']}, data['roles']) s = sqlalchemy.select([group_project_table.c.data]).where( (group_project_table.c.group_id == base_data['group']['id']) & (group_project_table.c.project_id == base_data['project']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': base_data['roles'][3]['id']}, data['roles']) s = sqlalchemy.select([group_project_table.c.data]).where( (group_project_table.c.group_id == base_data['group']['id']) & (group_project_table.c.project_id == base_data['project2']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 2) self.assertIn({'id': base_data['roles'][4]['id']}, data['roles']) self.assertIn({'id': base_data['roles'][5]['id']}, data['roles']) s = sqlalchemy.select([group_domain_table.c.data]).where( (group_domain_table.c.group_id == base_data['group']['id']) & (group_domain_table.c.domain_id == base_data['domain']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 2) self.assertIn({'id': base_data['roles'][6]['id']}, data['roles']) self.assertIn({'id': base_data['roles'][7]['id'], 'inherited_to': 'projects'}, data['roles']) s = sqlalchemy.select([user_domain_table.c.data]).where( (user_domain_table.c.user_id == base_data['user']['id']) & (user_domain_table.c.domain_id == base_data['domain']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 1) self.assertIn({'id': base_data['roles'][8]['id'], 'inherited_to': 'projects'}, data['roles']) s = sqlalchemy.select([user_domain_table.c.data]).where( (user_domain_table.c.user_id == base_data['user']['id']) & (user_domain_table.c.domain_id == base_data['domain2']['id'])) r = session.execute(s) data = json.loads(r.fetchone()['data']) self.assertEqual(len(data['roles']), 2) self.assertIn({'id': base_data['roles'][6]['id']}, data['roles']) self.assertIn({'id': base_data['roles'][7]['id']}, data['roles']) def check_assignments(session, base_data): def check_assignment_type(refs, type): for ref in refs: self.assertEqual(ref.type, type) assignment_table = sqlalchemy.Table( 'assignment', self.metadata, autoload=True) refs = session.query(assignment_table).all() self.assertEqual(len(refs), 11) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['user']['id']) q = q.filter_by(target_id=base_data['project']['id']) refs = q.all() self.assertEqual(len(refs), 1) self.assertEqual(refs[0].role_id, base_data['roles'][0]['id']) self.assertFalse(refs[0].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.USER_PROJECT) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['user']['id']) q = q.filter_by(target_id=base_data['project2']['id']) refs = q.all() self.assertEqual(len(refs), 2) role_ids = [base_data['roles'][1]['id'], base_data['roles'][2]['id']] self.assertIn(refs[0].role_id, role_ids) self.assertIn(refs[1].role_id, role_ids) self.assertFalse(refs[0].inherited) self.assertFalse(refs[1].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.USER_PROJECT) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['group']['id']) q = q.filter_by(target_id=base_data['project']['id']) refs = q.all() self.assertEqual(len(refs), 1) self.assertEqual(refs[0].role_id, base_data['roles'][3]['id']) self.assertFalse(refs[0].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.GROUP_PROJECT) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['group']['id']) q = q.filter_by(target_id=base_data['project2']['id']) refs = q.all() self.assertEqual(len(refs), 2) role_ids = [base_data['roles'][4]['id'], base_data['roles'][5]['id']] self.assertIn(refs[0].role_id, role_ids) self.assertIn(refs[1].role_id, role_ids) self.assertFalse(refs[0].inherited) self.assertFalse(refs[1].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.GROUP_PROJECT) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['group']['id']) q = q.filter_by(target_id=base_data['domain']['id']) refs = q.all() self.assertEqual(len(refs), 2) role_ids = [base_data['roles'][6]['id'], base_data['roles'][7]['id']] self.assertIn(refs[0].role_id, role_ids) self.assertIn(refs[1].role_id, role_ids) if refs[0].role_id == base_data['roles'][7]['id']: self.assertTrue(refs[0].inherited) self.assertFalse(refs[1].inherited) else: self.assertTrue(refs[1].inherited) self.assertFalse(refs[0].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.GROUP_DOMAIN) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['user']['id']) q = q.filter_by(target_id=base_data['domain']['id']) refs = q.all() self.assertEqual(len(refs), 1) self.assertEqual(refs[0].role_id, base_data['roles'][8]['id']) self.assertTrue(refs[0].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.USER_DOMAIN) q = session.query(assignment_table) q = q.filter_by(actor_id=base_data['user']['id']) q = q.filter_by(target_id=base_data['domain2']['id']) refs = q.all() self.assertEqual(len(refs), 2) role_ids = [base_data['roles'][6]['id'], base_data['roles'][7]['id']] self.assertIn(refs[0].role_id, role_ids) self.assertIn(refs[1].role_id, role_ids) self.assertFalse(refs[0].inherited) self.assertFalse(refs[1].inherited) check_assignment_type(refs, assignment_sql.AssignmentType.USER_DOMAIN) self.upgrade(37) session = self.Session() self.assertTableDoesNotExist('assignment') base_data = create_base_data(session) populate_grants(session, base_data) check_grants(session, base_data) session.commit() session.close() self.upgrade(40) session = self.Session() self.assertTableExists('assignment') self.assertTableDoesNotExist('user_project_metadata') self.assertTableDoesNotExist('group_project_metadata') self.assertTableDoesNotExist('user_domain_metadata') self.assertTableDoesNotExist('group_domain_metadata') check_assignments(session, base_data) session.close() self.downgrade(37) session = self.Session() self.assertTableDoesNotExist('assignment') check_grants(session, base_data) session.close() def test_limited_trusts_upgrade(self): # make sure that the remaining_uses column is created self.upgrade(41) self.assertTableColumns('trust', ['id', 'trustor_user_id', 'trustee_user_id', 'project_id', 'impersonation', 'deleted_at', 'expires_at', 'extra', 'remaining_uses']) def test_limited_trusts_downgrade(self): # make sure that the remaining_uses column is removed self.upgrade(41) self.downgrade(40) self.assertTableColumns('trust', ['id', 'trustor_user_id', 'trustee_user_id', 'project_id', 'impersonation', 'deleted_at', 'expires_at', 'extra']) def test_limited_trusts_downgrade_trusts_cleanup(self): # make sure that only trusts with unlimited uses are kept in the # downgrade self.upgrade(41) session = self.Session() trust_table = sqlalchemy.Table( 'trust', self.metadata, autoload=True) limited_trust = { 'id': uuid.uuid4().hex, 'trustor_user_id': uuid.uuid4().hex, 'trustee_user_id': uuid.uuid4().hex, 'project_id': uuid.uuid4().hex, 'impersonation': True, 'remaining_uses': 5 } consumed_trust = { 'id': uuid.uuid4().hex, 'trustor_user_id': uuid.uuid4().hex, 'trustee_user_id': uuid.uuid4().hex, 'project_id': uuid.uuid4().hex, 'impersonation': True, 'remaining_uses': 0 } unlimited_trust = { 'id': uuid.uuid4().hex, 'trustor_user_id': uuid.uuid4().hex, 'trustee_user_id': uuid.uuid4().hex, 'project_id': uuid.uuid4().hex, 'impersonation': True, 'remaining_uses': None } self.insert_dict(session, 'trust', limited_trust) self.insert_dict(session, 'trust', consumed_trust) self.insert_dict(session, 'trust', unlimited_trust) trust_table = sqlalchemy.Table( 'trust', self.metadata, autoload=True) # we should have 3 trusts in base self.assertEqual(3, session.query(trust_table).count()) self.downgrade(40) session = self.Session() trust_table = sqlalchemy.Table( 'trust', self.metadata, autoload=True) # Now only one trust remains ... self.assertEqual(1, session.query(trust_table.columns.id).count()) # ... and this trust is the one that was not limited in uses self.assertEqual( unlimited_trust['id'], session.query(trust_table.columns.id).one()[0]) def test_upgrade_service_enabled_cols(self): """Migration 44 added `enabled` column to `service` table.""" self.upgrade(44) # Verify that there's an 'enabled' field. exp_cols = ['id', 'type', 'extra', 'enabled'] self.assertTableColumns('service', exp_cols) def test_downgrade_service_enabled_cols(self): """Check columns when downgrade to migration 43. The downgrade from migration 44 removes the `enabled` column from the `service` table. """ self.upgrade(44) self.downgrade(43) exp_cols = ['id', 'type', 'extra'] self.assertTableColumns('service', exp_cols) def test_upgrade_service_enabled_data(self): """Migration 44 has to migrate data from `extra` to `enabled`.""" session = self.Session() def add_service(**extra_data): service_id = uuid.uuid4().hex service = { 'id': service_id, 'type': uuid.uuid4().hex, 'extra': json.dumps(extra_data), } self.insert_dict(session, 'service', service) return service_id self.upgrade(43) # Different services with expected enabled and extra values, and a # description. random_attr_name = uuid.uuid4().hex random_attr_value = uuid.uuid4().hex random_attr = {random_attr_name: random_attr_value} random_attr_str = "%s='%s'" % (random_attr_name, random_attr_value) random_attr_enabled_false = {random_attr_name: random_attr_value, 'enabled': False} random_attr_enabled_false_str = 'enabled=False,%s' % random_attr_str services = [ # Some values for True. (add_service(), (True, {}), 'no enabled'), (add_service(enabled=True), (True, {}), 'enabled=True'), (add_service(enabled='true'), (True, {}), "enabled='true'"), (add_service(**random_attr), (True, random_attr), random_attr_str), (add_service(enabled=None), (True, {}), 'enabled=None'), # Some values for False. (add_service(enabled=False), (False, {}), 'enabled=False'), (add_service(enabled='false'), (False, {}), "enabled='false'"), (add_service(enabled='0'), (False, {}), "enabled='0'"), (add_service(**random_attr_enabled_false), (False, random_attr), random_attr_enabled_false_str), ] self.upgrade(44) # Verify that the services have the expected values. self.metadata.clear() service_table = sqlalchemy.Table('service', self.metadata, autoload=True) def fetch_service(service_id): cols = [service_table.c.enabled, service_table.c.extra] f = service_table.c.id == service_id s = sqlalchemy.select(cols).where(f) ep = session.execute(s).fetchone() return ep.enabled, json.loads(ep.extra) for service_id, exp, msg in services: exp_enabled, exp_extra = exp enabled, extra = fetch_service(service_id) self.assertIs(exp_enabled, enabled, msg) self.assertEqual(exp_extra, extra, msg) def test_downgrade_service_enabled_data(self): """Downgrade from migration 44 migrates data. Downgrade from migration 44 migrates data from `enabled` to `extra`. Any disabled services have 'enabled': False put into 'extra'. """ session = self.Session() def add_service(enabled=True, **extra_data): service_id = uuid.uuid4().hex service = { 'id': service_id, 'type': uuid.uuid4().hex, 'extra': json.dumps(extra_data), 'enabled': enabled } self.insert_dict(session, 'service', service) return service_id self.upgrade(44) # Insert some services using the new format. # We'll need a service entry since it's the foreign key for services. service_id = add_service(True) new_service = (lambda enabled, **extra_data: add_service(enabled, **extra_data)) # Different services with expected extra values, and a # description. services = [ # True tests (new_service(True), {}, 'enabled'), (new_service(True, something='whatever'), {'something': 'whatever'}, "something='whatever'"), # False tests (new_service(False), {'enabled': False}, 'enabled=False'), (new_service(False, something='whatever'), {'enabled': False, 'something': 'whatever'}, "enabled=False, something='whatever'"), ] self.downgrade(43) # Verify that the services have the expected values. self.metadata.clear() service_table = sqlalchemy.Table('service', self.metadata, autoload=True) def fetch_service(service_id): cols = [service_table.c.extra] f = service_table.c.id == service_id s = sqlalchemy.select(cols).where(f) ep = session.execute(s).fetchone() return json.loads(ep.extra) for service_id, exp_extra, msg in services: extra = fetch_service(service_id) self.assertEqual(exp_extra, extra, msg) def test_upgrade_endpoint_enabled_cols(self): """Migration 42 added `enabled` column to `endpoint` table.""" self.upgrade(42) # Verify that there's an 'enabled' field. exp_cols = ['id', 'legacy_endpoint_id', 'interface', 'region', 'service_id', 'url', 'extra', 'enabled'] self.assertTableColumns('endpoint', exp_cols) def test_downgrade_endpoint_enabled_cols(self): """Check columns when downgrade from migration 41. The downgrade from migration 42 removes the `enabled` column from the `endpoint` table. """ self.upgrade(42) self.downgrade(41) exp_cols = ['id', 'legacy_endpoint_id', 'interface', 'region', 'service_id', 'url', 'extra'] self.assertTableColumns('endpoint', exp_cols) def test_upgrade_endpoint_enabled_data(self): """Migration 42 has to migrate data from `extra` to `enabled`.""" session = self.Session() def add_service(): service_id = uuid.uuid4().hex service = { 'id': service_id, 'type': uuid.uuid4().hex } self.insert_dict(session, 'service', service) return service_id def add_endpoint(service_id, **extra_data): endpoint_id = uuid.uuid4().hex endpoint = { 'id': endpoint_id, 'interface': uuid.uuid4().hex[:8], 'service_id': service_id, 'url': uuid.uuid4().hex, 'extra': json.dumps(extra_data) } self.insert_dict(session, 'endpoint', endpoint) return endpoint_id self.upgrade(41) # Insert some endpoints using the old format where `enabled` is in # `extra` JSON. # We'll need a service entry since it's the foreign key for endpoints. service_id = add_service() new_ep = lambda **extra_data: add_endpoint(service_id, **extra_data) # Different endpoints with expected enabled and extra values, and a # description. random_attr_name = uuid.uuid4().hex random_attr_value = uuid.uuid4().hex random_attr = {random_attr_name: random_attr_value} random_attr_str = "%s='%s'" % (random_attr_name, random_attr_value) random_attr_enabled_false = {random_attr_name: random_attr_value, 'enabled': False} random_attr_enabled_false_str = 'enabled=False,%s' % random_attr_str endpoints = [ # Some values for True. (new_ep(), (True, {}), 'no enabled'), (new_ep(enabled=True), (True, {}), 'enabled=True'), (new_ep(enabled='true'), (True, {}), "enabled='true'"), (new_ep(**random_attr), (True, random_attr), random_attr_str), (new_ep(enabled=None), (True, {}), 'enabled=None'), # Some values for False. (new_ep(enabled=False), (False, {}), 'enabled=False'), (new_ep(enabled='false'), (False, {}), "enabled='false'"), (new_ep(enabled='0'), (False, {}), "enabled='0'"), (new_ep(**random_attr_enabled_false), (False, random_attr), random_attr_enabled_false_str), ] self.upgrade(42) # Verify that the endpoints have the expected values. self.metadata.clear() endpoint_table = sqlalchemy.Table('endpoint', self.metadata, autoload=True) def fetch_endpoint(endpoint_id): cols = [endpoint_table.c.enabled, endpoint_table.c.extra] f = endpoint_table.c.id == endpoint_id s = sqlalchemy.select(cols).where(f) ep = session.execute(s).fetchone() return ep.enabled, json.loads(ep.extra) for endpoint_id, exp, msg in endpoints: exp_enabled, exp_extra = exp enabled, extra = fetch_endpoint(endpoint_id) self.assertIs(exp_enabled, enabled, msg) self.assertEqual(exp_extra, extra, msg) def test_downgrade_endpoint_enabled_data(self): """Downgrade from migration 42 migrates data. Downgrade from migration 42 migrates data from `enabled` to `extra`. Any disabled endpoints have 'enabled': False put into 'extra'. """ session = self.Session() def add_service(): service_id = uuid.uuid4().hex service = { 'id': service_id, 'type': uuid.uuid4().hex } self.insert_dict(session, 'service', service) return service_id def add_endpoint(service_id, enabled, **extra_data): endpoint_id = uuid.uuid4().hex endpoint = { 'id': endpoint_id, 'interface': uuid.uuid4().hex[:8], 'service_id': service_id, 'url': uuid.uuid4().hex, 'extra': json.dumps(extra_data), 'enabled': enabled } self.insert_dict(session, 'endpoint', endpoint) return endpoint_id self.upgrade(42) # Insert some endpoints using the new format. # We'll need a service entry since it's the foreign key for endpoints. service_id = add_service() new_ep = (lambda enabled, **extra_data: add_endpoint(service_id, enabled, **extra_data)) # Different endpoints with expected extra values, and a # description. endpoints = [ # True tests (new_ep(True), {}, 'enabled'), (new_ep(True, something='whatever'), {'something': 'whatever'}, "something='whatever'"), # False tests (new_ep(False), {'enabled': False}, 'enabled=False'), (new_ep(False, something='whatever'), {'enabled': False, 'something': 'whatever'}, "enabled=False, something='whatever'"), ] self.downgrade(41) # Verify that the endpoints have the expected values. self.metadata.clear() endpoint_table = sqlalchemy.Table('endpoint', self.metadata, autoload=True) def fetch_endpoint(endpoint_id): cols = [endpoint_table.c.extra] f = endpoint_table.c.id == endpoint_id s = sqlalchemy.select(cols).where(f) ep = session.execute(s).fetchone() return json.loads(ep.extra) for endpoint_id, exp_extra, msg in endpoints: extra = fetch_endpoint(endpoint_id) self.assertEqual(exp_extra, extra, msg) def test_upgrade_region_non_unique_description(self): """Test upgrade to migration 43. This migration should occur with no unique constraint on the region description column. Create two regions with the same description. """ session = self.Session() def add_region(): region_uuid = uuid.uuid4().hex region = { 'id': region_uuid, 'description': '' } self.insert_dict(session, 'region', region) return region_uuid self.upgrade(43) # Write one region to the database add_region() # Write another region to the database with the same description add_region() def test_upgrade_region_unique_description(self): """Test upgrade to migration 43. This test models a migration where there is a unique constraint on the description column. Create two regions with the same description. """ session = self.Session() def add_region(table): region_uuid = uuid.uuid4().hex region = { 'id': region_uuid, 'description': '' } self.insert_dict(session, 'region', region, table=table) return region_uuid def get_metadata(): meta = sqlalchemy.MetaData() meta.bind = self.engine return meta # Migrate to version 42 self.upgrade(42) region_table = sqlalchemy.Table('region', get_metadata(), autoload=True) # create the unique constraint and load the new version of the # reflection cache idx = sqlalchemy.Index('description', region_table.c.description, unique=True) idx.create(self.engine) region_unique_table = sqlalchemy.Table('region', get_metadata(), autoload=True) add_region(region_unique_table) self.assertEqual(1, session.query(region_unique_table).count()) # verify the unique constraint is enforced self.assertRaises(sqlalchemy.exc.IntegrityError, add_region, table=region_unique_table) # migrate to 43, unique constraint should be dropped self.upgrade(43) # reload the region table from the schema region_nonunique = sqlalchemy.Table('region', get_metadata(), autoload=True) self.assertEqual(1, session.query(region_nonunique).count()) # Write a second region to the database with the same description add_region(region_nonunique) self.assertEqual(2, session.query(region_nonunique).count()) def populate_user_table(self, with_pass_enab=False, with_pass_enab_domain=False): # Populate the appropriate fields in the user # table, depending on the parameters: # # Default: id, name, extra # pass_enab: Add password, enabled as well # pass_enab_domain: Add password, enabled and domain as well # this_table = sqlalchemy.Table("user", self.metadata, autoload=True) for user in default_fixtures.USERS: extra = copy.deepcopy(user) extra.pop('id') extra.pop('name') if with_pass_enab: password = extra.pop('password', None) enabled = extra.pop('enabled', True) ins = this_table.insert().values( {'id': user['id'], 'name': user['name'], 'password': password, 'enabled': bool(enabled), 'extra': json.dumps(extra)}) else: if with_pass_enab_domain: password = extra.pop('password', None) enabled = extra.pop('enabled', True) extra.pop('domain_id') ins = this_table.insert().values( {'id': user['id'], 'name': user['name'], 'domain_id': user['domain_id'], 'password': password, 'enabled': bool(enabled), 'extra': json.dumps(extra)}) else: ins = this_table.insert().values( {'id': user['id'], 'name': user['name'], 'extra': json.dumps(extra)}) self.engine.execute(ins) def populate_tenant_table(self, with_desc_enab=False, with_desc_enab_domain=False): # Populate the appropriate fields in the tenant or # project table, depending on the parameters # # Default: id, name, extra # desc_enab: Add description, enabled as well # desc_enab_domain: Add description, enabled and domain as well, # plus use project instead of tenant # if with_desc_enab_domain: # By this time tenants are now projects this_table = sqlalchemy.Table("project", self.metadata, autoload=True) else: this_table = sqlalchemy.Table("tenant", self.metadata, autoload=True) for tenant in default_fixtures.TENANTS: extra = copy.deepcopy(tenant) extra.pop('id') extra.pop('name') if with_desc_enab: desc = extra.pop('description', None) enabled = extra.pop('enabled', True) ins = this_table.insert().values( {'id': tenant['id'], 'name': tenant['name'], 'description': desc, 'enabled': bool(enabled), 'extra': json.dumps(extra)}) else: if with_desc_enab_domain: desc = extra.pop('description', None) enabled = extra.pop('enabled', True) extra.pop('domain_id') ins = this_table.insert().values( {'id': tenant['id'], 'name': tenant['name'], 'domain_id': tenant['domain_id'], 'description': desc, 'enabled': bool(enabled), 'extra': json.dumps(extra)}) else: ins = this_table.insert().values( {'id': tenant['id'], 'name': tenant['name'], 'extra': json.dumps(extra)}) self.engine.execute(ins) def _mysql_check_all_tables_innodb(self): database = self.engine.url.database connection = self.engine.connect() # sanity check total = connection.execute("SELECT count(*) " "from information_schema.TABLES " "where TABLE_SCHEMA='%(database)s'" % dict(database=database)) self.assertTrue(total.scalar() > 0, "No tables found. Wrong schema?") noninnodb = connection.execute("SELECT table_name " "from information_schema.TABLES " "where TABLE_SCHEMA='%(database)s' " "and ENGINE!='InnoDB' " "and TABLE_NAME!='migrate_version'" % dict(database=database)) names = [x[0] for x in noninnodb] self.assertEqual(names, [], "Non-InnoDB tables exist") connection.close() class VersionTests(SqlMigrateBase): def test_core_initial(self): """When get the version before migrated, it's 0.""" version = migration_helpers.get_db_version() self.assertEqual(0, version) def test_core_max(self): """When get the version after upgrading, it's the new version.""" self.upgrade(self.max_version) version = migration_helpers.get_db_version() self.assertEqual(self.max_version, version) def test_extension_not_controlled(self): """When get the version before controlling, raises DbMigrationError.""" self.assertRaises(db_exception.DbMigrationError, migration_helpers.get_db_version, extension='federation') def test_extension_initial(self): """When get the initial version of an extension, it's 0.""" abs_path = migration_helpers.find_migrate_repo(federation) migration.db_version_control(sql.get_engine(), abs_path) version = migration_helpers.get_db_version(extension='federation') self.assertEqual(0, version) def test_extension_migrated(self): """When get the version after migrating an extension, it's not 0.""" abs_path = migration_helpers.find_migrate_repo(federation) migration.db_version_control(sql.get_engine(), abs_path) migration.db_sync(sql.get_engine(), abs_path) version = migration_helpers.get_db_version(extension='federation') self.assertTrue(version > 0, "Version didn't change after migrated?") def test_unexpected_extension(self): """The version for an extension that doesn't exist raises ImportError. """ extension_name = uuid.uuid4().hex self.assertRaises(ImportError, migration_helpers.get_db_version, extension=extension_name) def test_unversioned_extension(self): """The version for extensions without migrations raise an exception. """ self.assertRaises(exception.MigrationNotProvided, migration_helpers.get_db_version, extension='access') keystone-2014.1/keystone/tests/test_catalog.py0000664000175400017540000001111212323716272022627 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import uuid import six from keystone.tests import rest BASE_URL = 'http://127.0.0.1:35357/v2' SERVICE_FIXTURE = object() class V2CatalogTestCase(rest.RestfulTestCase): def setUp(self): super(V2CatalogTestCase, self).setUp() self.service_id = uuid.uuid4().hex self.service = self.new_service_ref() self.service['id'] = self.service_id self.catalog_api.create_service( self.service_id, self.service.copy()) # TODO(termie): add an admin user to the fixtures and use that user # override the fixtures, for now self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_admin['id']) def new_ref(self): """Populates a ref with attributes common to all API entities.""" return { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, 'enabled': True} def new_service_ref(self): ref = self.new_ref() ref['type'] = uuid.uuid4().hex return ref def _get_token_id(self, r): """Applicable only to JSON.""" return r.result['access']['token']['id'] def _endpoint_create(self, expected_status=200, service_id=SERVICE_FIXTURE, publicurl='http://localhost:8080', internalurl='http://localhost:8080', adminurl='http://localhost:8080'): if service_id is SERVICE_FIXTURE: service_id = self.service_id # FIXME(dolph): expected status should actually be 201 Created path = '/v2.0/endpoints' body = { 'endpoint': { 'adminurl': adminurl, 'service_id': service_id, 'region': 'RegionOne', 'internalurl': internalurl, 'publicurl': publicurl } } r = self.admin_request(method='POST', token=self.get_scoped_token(), path=path, expected_status=expected_status, body=body) return body, r def test_endpoint_create(self): req_body, response = self._endpoint_create() self.assertTrue('endpoint' in response.result) self.assertTrue('id' in response.result['endpoint']) for field, value in six.iteritems(req_body['endpoint']): self.assertEqual(response.result['endpoint'][field], value) def test_endpoint_create_with_null_adminurl(self): req_body, response = self._endpoint_create(adminurl=None) self.assertEqual(req_body['endpoint']['adminurl'], None) self.assertNotIn('adminurl', response.result['endpoint']) def test_endpoint_create_with_empty_adminurl(self): req_body, response = self._endpoint_create(adminurl='') self.assertEqual(req_body['endpoint']['adminurl'], '') self.assertNotIn("adminurl", response.result['endpoint']) def test_endpoint_create_with_null_internalurl(self): req_body, response = self._endpoint_create(internalurl=None) self.assertEqual(req_body['endpoint']['internalurl'], None) self.assertNotIn('internalurl', response.result['endpoint']) def test_endpoint_create_with_empty_internalurl(self): req_body, response = self._endpoint_create(internalurl='') self.assertEqual(req_body['endpoint']['internalurl'], '') self.assertNotIn("internalurl", response.result['endpoint']) def test_endpoint_create_with_null_publicurl(self): self._endpoint_create(expected_status=400, publicurl=None) def test_endpoint_create_with_empty_publicurl(self): self._endpoint_create(expected_status=400, publicurl='') def test_endpoint_create_with_null_service_id(self): self._endpoint_create(expected_status=400, service_id=None) def test_endpoint_create_with_empty_service_id(self): self._endpoint_create(expected_status=400, service_id='') keystone-2014.1/keystone/tests/test_no_admin_token_auth.py0000664000175400017540000000424512323716267025237 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import os import webtest from keystone import tests class TestNoAdminTokenAuth(tests.TestCase): def setUp(self): super(TestNoAdminTokenAuth, self).setUp() self.load_backends() self._generate_paste_config() self.admin_app = webtest.TestApp( self.loadapp(tests.dirs.tmp('no_admin_token_auth'), name='admin'), extra_environ=dict(REMOTE_ADDR='127.0.0.1')) self.addCleanup(setattr, self, 'admin_app', None) def _generate_paste_config(self): # Generate a file, based on keystone-paste.ini, that doesn't include # admin_token_auth in the pipeline with open(tests.dirs.etc('keystone-paste.ini'), 'r') as f: contents = f.read() new_contents = contents.replace(' admin_token_auth ', ' ') filename = tests.dirs.tmp('no_admin_token_auth-paste.ini') with open(filename, 'w') as f: f.write(new_contents) self.addCleanup(os.remove, filename) def test_request_no_admin_token_auth(self): # This test verifies that if the admin_token_auth middleware isn't # in the paste pipeline that users can still make requests. # Note(blk-u): Picked /v2.0/tenants because it's an operation that # requires is_admin in the context, any operation that requires # is_admin would work for this test. REQ_PATH = '/v2.0/tenants' # If the following does not raise, then the test is successful. self.admin_app.get(REQ_PATH, headers={'X-Auth-Token': 'NotAdminToken'}, status=401) keystone-2014.1/keystone/tests/test_sizelimit.py0000664000175400017540000000411612323716267023240 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 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. import webob from keystone import config from keystone import exception from keystone import middleware from keystone import tests CONF = config.CONF MAX_REQUEST_BODY_SIZE = CONF.max_request_body_size class TestRequestBodySizeLimiter(tests.TestCase): def setUp(self): super(TestRequestBodySizeLimiter, self).setUp() @webob.dec.wsgify() def fake_app(req): return webob.Response(req.body) self.middleware = middleware.RequestBodySizeLimiter(fake_app) self.request = webob.Request.blank('/', method='POST') def test_content_length_acceptable(self): self.request.headers['Content-Length'] = MAX_REQUEST_BODY_SIZE self.request.body = "0" * MAX_REQUEST_BODY_SIZE response = self.request.get_response(self.middleware) self.assertEqual(200, response.status_int) def test_content_length_too_large(self): self.request.headers['Content-Length'] = MAX_REQUEST_BODY_SIZE + 1 self.request.body = "0" * (MAX_REQUEST_BODY_SIZE + 1) self.assertRaises(exception.RequestTooLarge, self.request.get_response, self.middleware) def test_request_too_large_no_content_length(self): self.request.body = "0" * (MAX_REQUEST_BODY_SIZE + 1) self.request.headers['Content-Length'] = None self.assertRaises(exception.RequestTooLarge, self.request.get_response, self.middleware) keystone-2014.1/keystone/tests/core.py0000664000175400017540000006431712323716272021125 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from __future__ import absolute_import import atexit import copy import functools import os import re import shutil import socket import sys import time import warnings import fixtures import logging from paste import deploy import six import testtools from testtools import testcase import webob from keystone.openstack.common.fixture import mockpatch from keystone.openstack.common import gettextutils # NOTE(ayoung) # environment.use_eventlet must run before any of the code that will # call the eventlet monkeypatching. from keystone.common import environment environment.use_eventlet() from keystone import auth from keystone.common import dependency from keystone.common import kvs from keystone.common.kvs import core as kvs_core from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.common import utils as common_utils from keystone import config from keystone import exception from keystone import notifications from keystone.openstack.common.db import options as db_options from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.fixture import config as config_fixture from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone import service from keystone.tests import ksfixtures # NOTE(dstanek): Tests inheriting from TestCase depend on having the # policy_file command-line option declared before setUp runs. Importing the # oslo policy module automatically declares the option. from keystone.openstack.common import policy as common_policy # noqa config.configure() LOG = log.getLogger(__name__) PID = six.text_type(os.getpid()) TESTSDIR = os.path.dirname(os.path.abspath(__file__)) TESTCONF = os.path.join(TESTSDIR, 'config_files') ROOTDIR = os.path.normpath(os.path.join(TESTSDIR, '..', '..')) VENDOR = os.path.join(ROOTDIR, 'vendor') ETCDIR = os.path.join(ROOTDIR, 'etc') def _calc_tmpdir(): env_val = os.environ.get('KEYSTONE_TEST_TEMP_DIR') if not env_val: return os.path.join(TESTSDIR, 'tmp', PID) return os.path.join(env_val, PID) TMPDIR = _calc_tmpdir() CONF = config.CONF exception._FATAL_EXCEPTION_FORMAT_ERRORS = True os.makedirs(TMPDIR) atexit.register(shutil.rmtree, TMPDIR) class dirs: @staticmethod def root(*p): return os.path.join(ROOTDIR, *p) @staticmethod def etc(*p): return os.path.join(ETCDIR, *p) @staticmethod def tests(*p): return os.path.join(TESTSDIR, *p) @staticmethod def tmp(*p): return os.path.join(TMPDIR, *p) @staticmethod def tests_conf(*p): return os.path.join(TESTCONF, *p) # keystone.common.sql.initialize() for testing. DEFAULT_TEST_DB_FILE = dirs.tmp('test.db') def _initialize_sql_session(): # Make sure the DB is located in the correct location, in this case set # the default value, as this should be able to be overridden in some # test cases. db_file = DEFAULT_TEST_DB_FILE db_options.set_defaults( sql_connection='sqlite:///%s' % db_file, sqlite_db=db_file) _initialize_sql_session() def checkout_vendor(repo, rev): # TODO(termie): this function is a good target for some optimizations :PERF name = repo.split('/')[-1] if name.endswith('.git'): name = name[:-4] working_dir = os.getcwd() revdir = os.path.join(VENDOR, '%s-%s' % (name, rev.replace('/', '_'))) modcheck = os.path.join(VENDOR, '.%s-%s' % (name, rev.replace('/', '_'))) try: if os.path.exists(modcheck): mtime = os.stat(modcheck).st_mtime if int(time.time()) - mtime < 10000: return revdir if not os.path.exists(revdir): common_utils.git('clone', repo, revdir) os.chdir(revdir) common_utils.git('checkout', '-q', 'master') common_utils.git('pull', '-q') common_utils.git('checkout', '-q', rev) # write out a modified time with open(modcheck, 'w') as fd: fd.write('1') except environment.subprocess.CalledProcessError: LOG.warning(_('Failed to checkout %s'), repo) os.chdir(working_dir) return revdir def setup_database(): db = dirs.tmp('test.db') pristine = dirs.tmp('test.db.pristine') if os.path.exists(db): os.unlink(db) if not os.path.exists(pristine): migration.db_sync(sql.get_engine(), migration_helpers.find_migrate_repo()) migration_helpers.sync_database_to_version(extension='revoke') shutil.copyfile(db, pristine) else: shutil.copyfile(pristine, db) def teardown_database(): sql.cleanup() @atexit.register def remove_test_databases(): db = dirs.tmp('test.db') if os.path.exists(db): os.unlink(db) pristine = dirs.tmp('test.db.pristine') if os.path.exists(pristine): os.unlink(pristine) def generate_paste_config(extension_name): # Generate a file, based on keystone-paste.ini, that is named: # extension_name.ini, and includes extension_name in the pipeline with open(dirs.etc('keystone-paste.ini'), 'r') as f: contents = f.read() new_contents = contents.replace(' service_v3', ' %s service_v3' % (extension_name)) new_paste_file = dirs.tmp(extension_name + '.ini') with open(new_paste_file, 'w') as f: f.write(new_contents) return new_paste_file def remove_generated_paste_config(extension_name): # Remove the generated paste config file, named extension_name.ini paste_file_to_remove = dirs.tmp(extension_name + '.ini') os.remove(paste_file_to_remove) def skip_if_cache_disabled(*sections): """This decorator is used to skip a test if caching is disabled either globally or for the specific section. In the code fragment:: @skip_if_cache_is_disabled('assignment', 'token') def test_method(*args): ... The method test_method would be skipped if caching is disabled globally via the `enabled` option in the `cache` section of the configuration or if the `caching` option is set to false in either `assignment` or `token` sections of the configuration. This decorator can be used with no arguments to only check global caching. If a specified configuration section does not define the `caching` option, this decorator makes the same assumption as the `should_cache_fn` in keystone.common.cache that caching should be enabled. """ def wrapper(f): @functools.wraps(f) def inner(*args, **kwargs): if not CONF.cache.enabled: raise testcase.TestSkipped('Cache globally disabled.') for s in sections: conf_sec = getattr(CONF, s, None) if conf_sec is not None: if not getattr(conf_sec, 'caching', True): raise testcase.TestSkipped('%s caching disabled.' % s) return f(*args, **kwargs) return inner return wrapper class UnexpectedExit(Exception): pass class TestClient(object): def __init__(self, app=None, token=None): self.app = app self.token = token def request(self, method, path, headers=None, body=None): if headers is None: headers = {} if self.token: headers.setdefault('X-Auth-Token', self.token) req = webob.Request.blank(path) req.method = method for k, v in six.iteritems(headers): req.headers[k] = v if body: req.body = body return req.get_response(self.app) def get(self, path, headers=None): return self.request('GET', path=path, headers=headers) def post(self, path, headers=None, body=None): return self.request('POST', path=path, headers=headers, body=body) def put(self, path, headers=None, body=None): return self.request('PUT', path=path, headers=headers, body=body) class NoModule(object): """A mixin class to provide support for unloading/disabling modules.""" def setUp(self): super(NoModule, self).setUp() self._finders = [] def cleanup_finders(): for finder in self._finders: sys.meta_path.remove(finder) del self._finders self.addCleanup(cleanup_finders) self._cleared_modules = {} def cleanup_modules(): sys.modules.update(self._cleared_modules) del self._cleared_modules self.addCleanup(cleanup_modules) def clear_module(self, module): cleared_modules = {} for fullname in sys.modules.keys(): if fullname == module or fullname.startswith(module + '.'): cleared_modules[fullname] = sys.modules.pop(fullname) return cleared_modules def disable_module(self, module): """Ensure ImportError for the specified module.""" # Clear 'module' references in sys.modules self._cleared_modules.update(self.clear_module(module)) # Disallow further imports of 'module' class NoModule(object): def find_module(self, fullname, path): if fullname == module or fullname.startswith(module + '.'): raise ImportError finder = NoModule() self._finders.append(finder) sys.meta_path.insert(0, finder) class BaseTestCase(testtools.TestCase): """Light weight base test class. This is a placeholder that will eventually go away once thc setup/teardown in TestCase is properly trimmed down to the bare essentials. This is really just a play to speed up the tests by eliminating unnecessary work. """ def cleanup_instance(self, *names): """Create a function suitable for use with self.addCleanup. :returns: a callable that uses a closure to delete instance attributes """ def cleanup(): for name in names: # TODO(dstanek): remove this 'if' statement once # load_backend in test_backend_ldap is only called once # per test if hasattr(self, name): delattr(self, name) return cleanup @dependency.optional('revoke_api') class TestCase(BaseTestCase): _config_file_list = [] def config_files(self): return copy.copy(self._config_file_list) def config_overrides(self): self.config_fixture.config(policy_file=dirs.etc('policy.json')) self.config_fixture.config( group='auth', methods=['keystone.auth.plugins.external.DefaultDomain', 'keystone.auth.plugins.password.Password', 'keystone.auth.plugins.token.Token', 'keystone.auth.plugins.oauth1.OAuth', 'keystone.auth.plugins.saml2.Saml2']) self.config_fixture.config( # TODO(morganfainberg): Make Cache Testing a separate test case # in tempest, and move it out of the base unit tests. group='cache', backend='dogpile.cache.memory', enabled=True, proxies=['keystone.tests.test_cache.CacheIsolatingProxy']) self.config_fixture.config( group='catalog', driver='keystone.catalog.backends.templated.Catalog', template_file=dirs.tests('default_catalog.templates')) self.config_fixture.config( group='identity', driver='keystone.identity.backends.kvs.Identity') self.config_fixture.config( group='kvs', backends=[ 'keystone.tests.test_kvs.KVSBackendForcedKeyMangleFixture', 'keystone.tests.test_kvs.KVSBackendFixture']) self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.kvs.Revoke') self.config_fixture.config( group='signing', certfile='examples/pki/certs/signing_cert.pem', keyfile='examples/pki/private/signing_key.pem', ca_certs='examples/pki/certs/cacert.pem') self.config_fixture.config( group='token', driver='keystone.token.backends.kvs.Token') self.config_fixture.config( group='trust', driver='keystone.trust.backends.kvs.Trust') def setUp(self): super(TestCase, self).setUp() self.addCleanup(self.cleanup_instance( '_paths', '_memo', '_overrides', '_group_overrides', 'maxDiff', 'exit_patch', 'config_fixture', 'logger')) self._paths = [] def _cleanup_paths(): for path in self._paths: if path in sys.path: sys.path.remove(path) self.addCleanup(_cleanup_paths) self._memo = {} self._overrides = [] self._group_overrides = {} # show complete diffs on failure self.maxDiff = None self.addCleanup(CONF.reset) self.exit_patch = self.useFixture(mockpatch.PatchObject(sys, 'exit')) self.exit_patch.mock.side_effect = UnexpectedExit self.config_fixture = self.useFixture(config_fixture.Config(CONF)) self.config(self.config_files()) self.config_overrides() self.logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) warnings.filterwarnings('ignore', category=DeprecationWarning) self.useFixture(ksfixtures.Cache()) # Clear the registry of providers so that providers from previous # tests aren't used. self.addCleanup(dependency.reset) self.addCleanup(kvs.INMEMDB.clear) # Ensure Notification subscriotions and resource types are empty self.addCleanup(notifications.SUBSCRIBERS.clear) self.addCleanup(notifications._reset_notifier) # Reset the auth-plugin registry self.addCleanup(self.clear_auth_plugin_registry) def config(self, config_files): CONF(args=[], project='keystone', default_config_files=config_files) def load_backends(self): """Initializes each manager and assigns them to an attribute.""" # TODO(blk-u): Shouldn't need to clear the registry here, but some # tests call load_backends multiple times. These should be fixed to # only call load_backends once. dependency.reset() # TODO(morganfainberg): Shouldn't need to clear the registry here, but # some tests call load_backends multiple times. Since it is not # possible to re-configure a backend, we need to clear the list. This # should eventually be removed once testing has been cleaned up. kvs_core.KEY_VALUE_STORE_REGISTRY.clear() self.clear_auth_plugin_registry() drivers = service.load_backends() drivers.update(dependency.resolve_future_dependencies()) for manager_name, manager in six.iteritems(drivers): setattr(self, manager_name, manager) self.addCleanup(self.cleanup_instance(*drivers.keys())) # The credential backend only supports SQL, so we always have to load # the tables. self.engine = sql.get_engine() self.addCleanup(sql.cleanup) self.addCleanup(self.cleanup_instance('engine')) sql.ModelBase.metadata.create_all(bind=self.engine) self.addCleanup(sql.ModelBase.metadata.drop_all, bind=self.engine) def load_fixtures(self, fixtures): """Hacky basic and naive fixture loading based on a python module. Expects that the various APIs into the various services are already defined on `self`. """ # NOTE(dstanek): create a list of attribute names to be removed # from this instance during cleanup fixtures_to_cleanup = [] # TODO(termie): doing something from json, probably based on Django's # loaddata will be much preferred. if hasattr(self, 'identity_api') and hasattr(self, 'assignment_api'): for domain in fixtures.DOMAINS: try: rv = self.assignment_api.create_domain(domain['id'], domain) except exception.Conflict: rv = self.assignment_api.get_domain(domain['id']) except exception.NotImplemented: rv = domain attrname = 'domain_%s' % domain['id'] setattr(self, attrname, rv) fixtures_to_cleanup.append(attrname) for tenant in fixtures.TENANTS: try: rv = self.assignment_api.create_project( tenant['id'], tenant) except exception.Conflict: rv = self.assignment_api.get_project(tenant['id']) attrname = 'tenant_%s' % tenant['id'] setattr(self, attrname, rv) fixtures_to_cleanup.append(attrname) for role in fixtures.ROLES: try: rv = self.assignment_api.create_role(role['id'], role) except exception.Conflict: rv = self.assignment_api.get_role(role['id']) attrname = 'role_%s' % role['id'] setattr(self, attrname, rv) fixtures_to_cleanup.append(attrname) for user in fixtures.USERS: user_copy = user.copy() tenants = user_copy.pop('tenants') try: self.identity_api.create_user(user['id'], user_copy) except exception.Conflict: pass for tenant_id in tenants: try: self.assignment_api.add_user_to_project(tenant_id, user['id']) except exception.Conflict: pass attrname = 'user_%s' % user['id'] setattr(self, attrname, user_copy) fixtures_to_cleanup.append(attrname) self.addCleanup(self.cleanup_instance(*fixtures_to_cleanup)) def _paste_config(self, config): if not config.startswith('config:'): test_path = os.path.join(TESTSDIR, config) etc_path = os.path.join(ROOTDIR, 'etc', config) for path in [test_path, etc_path]: if os.path.exists('%s-paste.ini' % path): return 'config:%s-paste.ini' % path return config def loadapp(self, config, name='main'): return deploy.loadapp(self._paste_config(config), name=name) def client(self, app, *args, **kw): return TestClient(app, *args, **kw) def add_path(self, path): sys.path.insert(0, path) self._paths.append(path) def clear_auth_plugin_registry(self): auth.controllers.AUTH_METHODS.clear() auth.controllers.AUTH_PLUGINS_LOADED = False def assertCloseEnoughForGovernmentWork(self, a, b, delta=3): """Asserts that two datetimes are nearly equal within a small delta. :param delta: Maximum allowable time delta, defined in seconds. """ msg = '%s != %s within %s delta' % (a, b, delta) self.assertTrue(abs(a - b).seconds <= delta, msg) def assertNotEmpty(self, l): self.assertTrue(len(l)) def assertDictEqual(self, d1, d2, msg=None): self.assertIsInstance(d1, dict) self.assertIsInstance(d2, dict) self.assertEqual(d1, d2, msg) def assertRaisesRegexp(self, expected_exception, expected_regexp, callable_obj, *args, **kwargs): """Asserts that the message in a raised exception matches a regexp. """ try: callable_obj(*args, **kwargs) except expected_exception as exc_value: if isinstance(expected_regexp, six.string_types): expected_regexp = re.compile(expected_regexp) if isinstance(exc_value.args[0], gettextutils.Message): if not expected_regexp.search(six.text_type(exc_value)): raise self.failureException( '"%s" does not match "%s"' % (expected_regexp.pattern, six.text_type(exc_value))) else: if not expected_regexp.search(str(exc_value)): raise self.failureException( '"%s" does not match "%s"' % (expected_regexp.pattern, str(exc_value))) else: if hasattr(expected_exception, '__name__'): excName = expected_exception.__name__ else: excName = str(expected_exception) raise self.failureException("%s not raised" % excName) def assertDictContainsSubset(self, expected, actual, msg=None): """Checks whether actual is a superset of expected.""" def safe_repr(obj, short=False): _MAX_LENGTH = 80 try: result = repr(obj) except Exception: result = object.__repr__(obj) if not short or len(result) < _MAX_LENGTH: return result return result[:_MAX_LENGTH] + ' [truncated]...' missing = [] mismatched = [] for key, value in six.iteritems(expected): if key not in actual: missing.append(key) elif value != actual[key]: mismatched.append('%s, expected: %s, actual: %s' % (safe_repr(key), safe_repr(value), safe_repr(actual[key]))) if not (missing or mismatched): return standardMsg = '' if missing: standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in missing) if mismatched: if standardMsg: standardMsg += '; ' standardMsg += 'Mismatched values: %s' % ','.join(mismatched) self.fail(self._formatMessage(msg, standardMsg)) @property def ipv6_enabled(self): if socket.has_ipv6: sock = None try: sock = socket.socket(socket.AF_INET6) # NOTE(Mouad): Try to bind to IPv6 loopback ip address. sock.bind(("::1", 0)) return True except socket.error: pass finally: if sock: sock.close() return False def skip_if_no_ipv6(self): if not self.ipv6_enabled: raise self.skipTest("IPv6 is not enabled in the system") def skip_if_env_not_set(self, env_var): if not os.environ.get(env_var): self.skipTest('Env variable %s is not set.' % env_var) def assertSetEqual(self, set1, set2, msg=None): # TODO(morganfainberg): Remove this and self._assertSetEqual once # support for python 2.6 is no longer needed. if (sys.version_info < (2, 7)): return self._assertSetEqual(set1, set2, msg=None) else: # use the native assertSetEqual return super(TestCase, self).assertSetEqual(set1, set2, msg=msg) def _assertSetEqual(self, set1, set2, msg=None): """A set-specific equality assertion. Args: set1: The first set to compare. set2: The second set to compare. msg: Optional message to use on failure instead of a list of differences. assertSetEqual uses ducktyping to support different types of sets, and is optimized for sets specifically (parameters must support a difference method). """ try: difference1 = set1.difference(set2) except TypeError as e: self.fail('invalid type when attempting set difference: %s' % e) except AttributeError as e: self.fail('first argument does not support set difference: %s' % e) try: difference2 = set2.difference(set1) except TypeError as e: self.fail('invalid type when attempting set difference: %s' % e) except AttributeError as e: self.fail('second argument does not support set difference: %s' % e) if not (difference1 or difference2): return lines = [] if difference1: lines.append('Items in the first set but not the second:') for item in difference1: lines.append(repr(item)) if difference2: lines.append('Items in the second set but not the first:') for item in difference2: lines.append(repr(item)) standardMsg = '\n'.join(lines) self.fail(self._formatMessage(msg, standardMsg)) class SQLDriverOverrides(object): """A mixin for consolidating sql-specific test overrides.""" def config_overrides(self): super(SQLDriverOverrides, self).config_overrides() # SQL specific driver overrides self.config_fixture.config( group='catalog', driver='keystone.catalog.backends.sql.Catalog') self.config_fixture.config( group='ec2', driver='keystone.contrib.ec2.backends.sql.Ec2') self.config_fixture.config( group='identity', driver='keystone.identity.backends.sql.Identity') self.config_fixture.config( group='policy', driver='keystone.policy.backends.sql.Policy') self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.sql.Revoke') self.config_fixture.config( group='token', driver='keystone.token.backends.sql.Token') self.config_fixture.config( group='trust', driver='keystone.trust.backends.sql.Trust') keystone-2014.1/keystone/tests/test_revoke.py0000664000175400017540000004237012323716272022522 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import datetime import uuid import mock from keystone.common import dependency from keystone import config from keystone.contrib.revoke import model from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import test_backend_sql CONF = config.CONF def _new_id(): return uuid.uuid4().hex def _future_time(): expire_delta = datetime.timedelta(seconds=1000) future_time = timeutils.utcnow() + expire_delta return future_time def _past_time(): expire_delta = datetime.timedelta(days=-1000) past_time = timeutils.utcnow() + expire_delta return past_time def _sample_blank_token(): issued_delta = datetime.timedelta(minutes=-2) issued_at = timeutils.utcnow() + issued_delta token_data = model.blank_token_data(issued_at) return token_data def _matches(event, token_values): """See if the token matches the revocation event. Used as a secondary check on the logic to Check By Tree Below: This is abrute force approach to checking. Compare each attribute from the event with the corresponding value from the token. If the event does not have a value for the attribute, a match is still possible. If the event has a value for the attribute, and it does not match the token, no match is possible, so skip the remaining checks. :param event one revocation event to match :param token_values dictionary with set of values taken from the token :returns if the token matches the revocation event, indicating the token has been revoked """ # The token has three attributes that can match the user_id if event.user_id is not None: for attribute_name in ['user_id', 'trustor_id', 'trustee_id']: if event.user_id == token_values[attribute_name]: break else: return False # The token has two attributes that can match the domain_id if event.domain_id is not None: dom_id_matched = False for attribute_name in ['user_domain_id', 'project_domain_id']: if event.domain_id == token_values[attribute_name]: dom_id_matched = True break if not dom_id_matched: return False # If any one check does not match, the while token does # not match the event. The numerous return False indicate # that the token is still valid and short-circuits the # rest of the logic. attribute_names = ['project_id', 'expires_at', 'trust_id', 'consumer_id', 'access_token_id'] for attribute_name in attribute_names: if getattr(event, attribute_name) is not None: if (getattr(event, attribute_name) != token_values[attribute_name]): return False if event.role_id is not None: roles = token_values['roles'] role_found = False for role in roles: if event.role_id == role: role_found = True break if not role_found: return False if token_values['issued_at'] > event.issued_before: return False return True @dependency.requires('revoke_api') class RevokeTests(object): def test_list(self): self.revoke_api.revoke_by_user(user_id=1) self.assertEqual(1, len(self.revoke_api.get_events())) self.revoke_api.revoke_by_user(user_id=2) self.assertEqual(2, len(self.revoke_api.get_events())) def test_list_since(self): self.revoke_api.revoke_by_user(user_id=1) self.revoke_api.revoke_by_user(user_id=2) past = timeutils.utcnow() - datetime.timedelta(seconds=1000) self.assertEqual(2, len(self.revoke_api.get_events(past))) future = timeutils.utcnow() + datetime.timedelta(seconds=1000) self.assertEqual(0, len(self.revoke_api.get_events(future))) def test_past_expiry_are_removed(self): user_id = 1 self.revoke_api.revoke_by_expiration(user_id, _future_time()) self.assertEqual(1, len(self.revoke_api.get_events())) event = model.RevokeEvent() event.revoked_at = _past_time() self.revoke_api.revoke(event) self.assertEqual(1, len(self.revoke_api.get_events())) @mock.patch.object(timeutils, 'utcnow') def test_expired_events_removed_validate_token_success(self, mock_utcnow): def _sample_token_values(): token = _sample_blank_token() token['expires_at'] = timeutils.isotime(_future_time(), subsecond=True) return token now = datetime.datetime.utcnow() now_plus_2h = now + datetime.timedelta(hours=2) mock_utcnow.return_value = now # Build a token and validate it. This will seed the cache for the # future 'synchronize' call. token_values = _sample_token_values() user_id = _new_id() self.revoke_api.revoke_by_user(user_id) token_values['user_id'] = user_id self.assertRaises(exception.TokenNotFound, self.revoke_api.check_token, token_values) # Move our clock forward by 2h, build a new token and validate it. # 'synchronize' should now be exercised and remove old expired events mock_utcnow.return_value = now_plus_2h self.revoke_api.revoke_by_expiration(_new_id(), now_plus_2h) #should no longer throw an exception self.revoke_api.check_token(token_values) class SqlRevokeTests(test_backend_sql.SqlTests, RevokeTests): def config_overrides(self): super(SqlRevokeTests, self).config_overrides() self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.sql.Revoke') self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider', revoke_by_id=False) class KvsRevokeTests(tests.TestCase, RevokeTests): def config_overrides(self): super(KvsRevokeTests, self).config_overrides() self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.kvs.Revoke') self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider', revoke_by_id=False) def setUp(self): super(KvsRevokeTests, self).setUp() self.load_backends() class RevokeTreeTests(tests.TestCase): def setUp(self): super(RevokeTreeTests, self).setUp() self.events = [] self.tree = model.RevokeTree() self._sample_data() def _sample_data(self): user_ids = [] project_ids = [] role_ids = [] for i in range(0, 3): user_ids.append(_new_id()) project_ids.append(_new_id()) role_ids.append(_new_id()) project_tokens = [] i = len(project_tokens) project_tokens.append(_sample_blank_token()) project_tokens[i]['user_id'] = user_ids[0] project_tokens[i]['project_id'] = project_ids[0] project_tokens[i]['roles'] = [role_ids[1]] i = len(project_tokens) project_tokens.append(_sample_blank_token()) project_tokens[i]['user_id'] = user_ids[1] project_tokens[i]['project_id'] = project_ids[0] project_tokens[i]['roles'] = [role_ids[0]] i = len(project_tokens) project_tokens.append(_sample_blank_token()) project_tokens[i]['user_id'] = user_ids[0] project_tokens[i]['project_id'] = project_ids[1] project_tokens[i]['roles'] = [role_ids[0]] token_to_revoke = _sample_blank_token() token_to_revoke['user_id'] = user_ids[0] token_to_revoke['project_id'] = project_ids[0] token_to_revoke['roles'] = [role_ids[0]] self.project_tokens = project_tokens self.user_ids = user_ids self.project_ids = project_ids self.role_ids = role_ids self.token_to_revoke = token_to_revoke def _assertTokenRevoked(self, token_data): self.assertTrue(any([_matches(e, token_data) for e in self.events])) return self.assertTrue(self.tree.is_revoked(token_data), 'Token should be revoked') def _assertTokenNotRevoked(self, token_data): self.assertFalse(any([_matches(e, token_data) for e in self.events])) return self.assertFalse(self.tree.is_revoked(token_data), 'Token should not be revoked') def _revoke_by_user(self, user_id): return self.tree.add_event( model.RevokeEvent(user_id=user_id)) def _revoke_by_expiration(self, user_id, expires_at): event = self.tree.add_event( model.RevokeEvent(user_id=user_id, expires_at=expires_at)) self.events.append(event) return event def _revoke_by_grant(self, role_id, user_id=None, domain_id=None, project_id=None): event = self.tree.add_event( model.RevokeEvent(user_id=user_id, role_id=role_id, domain_id=domain_id, project_id=project_id)) self.events.append(event) return event def _revoke_by_user_and_project(self, user_id, project_id): event = self.tree.add_event( model.RevokeEvent(project_id=project_id, user_id=user_id)) self.events.append(event) return event def _revoke_by_project_role_assignment(self, project_id, role_id): event = self.tree.add_event( model.RevokeEvent(project_id=project_id, role_id=role_id)) self.events.append(event) return event def _revoke_by_domain_role_assignment(self, domain_id, role_id): event = self.tree.add_event( model.RevokeEvent(domain_id=domain_id, role_id=role_id)) self.events.append(event) return event def _user_field_test(self, field_name): user_id = _new_id() event = self._revoke_by_user(user_id) self.events.append(event) token_data_u1 = _sample_blank_token() token_data_u1[field_name] = user_id self._assertTokenRevoked(token_data_u1) token_data_u2 = _sample_blank_token() token_data_u2[field_name] = _new_id() self._assertTokenNotRevoked(token_data_u2) self.tree.remove_event(event) self.events.remove(event) self._assertTokenNotRevoked(token_data_u1) def test_revoke_by_user(self): self._user_field_test('user_id') def test_revoke_by_user_matches_trustee(self): self._user_field_test('trustee_id') def test_revoke_by_user_matches_trustor(self): self._user_field_test('trustor_id') def test_by_user_expiration(self): future_time = _future_time() user_id = 1 event = self._revoke_by_expiration(user_id, future_time) token_data_1 = _sample_blank_token() token_data_1['user_id'] = user_id token_data_1['expires_at'] = future_time self._assertTokenRevoked(token_data_1) token_data_2 = _sample_blank_token() token_data_2['user_id'] = user_id expire_delta = datetime.timedelta(seconds=2000) future_time = timeutils.utcnow() + expire_delta token_data_2['expires_at'] = future_time self._assertTokenNotRevoked(token_data_2) self.removeEvent(event) self._assertTokenNotRevoked(token_data_1) def removeEvent(self, event): self.events.remove(event) self.tree.remove_event(event) def test_by_project_grant(self): token_to_revoke = self.token_to_revoke tokens = self.project_tokens self._assertTokenNotRevoked(token_to_revoke) for token in tokens: self._assertTokenNotRevoked(token) event = self._revoke_by_grant(role_id=self.role_ids[0], user_id=self.user_ids[0], project_id=self.project_ids[0]) self._assertTokenRevoked(token_to_revoke) for token in tokens: self._assertTokenNotRevoked(token) self.removeEvent(event) self._assertTokenNotRevoked(token_to_revoke) for token in tokens: self._assertTokenNotRevoked(token) token_to_revoke['roles'] = [self.role_ids[0], self.role_ids[1], self.role_ids[2]] event = self._revoke_by_grant(role_id=self.role_ids[0], user_id=self.user_ids[0], project_id=self.project_ids[0]) self._assertTokenRevoked(token_to_revoke) self.removeEvent(event) self._assertTokenNotRevoked(token_to_revoke) event = self._revoke_by_grant(role_id=self.role_ids[1], user_id=self.user_ids[0], project_id=self.project_ids[0]) self._assertTokenRevoked(token_to_revoke) self.removeEvent(event) self._assertTokenNotRevoked(token_to_revoke) self._revoke_by_grant(role_id=self.role_ids[0], user_id=self.user_ids[0], project_id=self.project_ids[0]) self._revoke_by_grant(role_id=self.role_ids[1], user_id=self.user_ids[0], project_id=self.project_ids[0]) self._revoke_by_grant(role_id=self.role_ids[2], user_id=self.user_ids[0], project_id=self.project_ids[0]) self._assertTokenRevoked(token_to_revoke) def test_by_project_and_user_and_role(self): user_id1 = _new_id() user_id2 = _new_id() project_id = _new_id() self.events.append(self._revoke_by_user(user_id1)) self.events.append( self._revoke_by_user_and_project(user_id2, project_id)) token_data = _sample_blank_token() token_data['user_id'] = user_id2 token_data['project_id'] = project_id self._assertTokenRevoked(token_data) def _assertEmpty(self, collection): return self.assertEqual(0, len(collection), "collection not empty") def _assertEventsMatchIteration(self, turn): self.assertEqual(1, len(self.tree.revoke_map)) self.assertEqual(turn + 1, len(self.tree.revoke_map ['trust_id=*'] ['consumer_id=*'] ['access_token_id=*'])) # two different functions add domain_ids, +1 for None self.assertEqual(2 * turn + 1, len(self.tree.revoke_map ['trust_id=*'] ['consumer_id=*'] ['access_token_id=*'] ['expires_at=*'])) # two different functions add project_ids, +1 for None self.assertEqual(2 * turn + 1, len(self.tree.revoke_map ['trust_id=*'] ['consumer_id=*'] ['access_token_id=*'] ['expires_at=*'] ['domain_id=*'])) # 10 users added self.assertEqual(turn, len(self.tree.revoke_map ['trust_id=*'] ['consumer_id=*'] ['access_token_id=*'] ['expires_at=*'] ['domain_id=*'] ['project_id=*'])) def test_cleanup(self): events = self.events self._assertEmpty(self.tree.revoke_map) for i in range(0, 10): events.append( self._revoke_by_user(_new_id())) events.append( self._revoke_by_expiration(_new_id(), _future_time())) events.append( self._revoke_by_project_role_assignment(_new_id(), _new_id())) events.append( self._revoke_by_domain_role_assignment(_new_id(), _new_id())) events.append( self._revoke_by_domain_role_assignment(_new_id(), _new_id())) events.append( self._revoke_by_user_and_project(_new_id(), _new_id())) self._assertEventsMatchIteration(i + 1) for event in self.events: self.tree.remove_event(event) self._assertEmpty(self.tree.revoke_map) keystone-2014.1/keystone/tests/test_backend_templated.py0000664000175400017540000000545412323716267024663 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import os from keystone import exception from keystone import tests from keystone.tests import default_fixtures from keystone.tests import test_backend DEFAULT_CATALOG_TEMPLATES = os.path.abspath(os.path.join( os.path.dirname(__file__), 'default_catalog.templates')) class TestTemplatedCatalog(tests.TestCase, test_backend.CatalogTests): DEFAULT_FIXTURE = { 'RegionOne': { 'compute': { 'adminURL': 'http://localhost:8774/v1.1/bar', 'publicURL': 'http://localhost:8774/v1.1/bar', 'internalURL': 'http://localhost:8774/v1.1/bar', 'name': "'Compute Service'", 'id': '2' }, 'identity': { 'adminURL': 'http://localhost:35357/v2.0', 'publicURL': 'http://localhost:5000/v2.0', 'internalURL': 'http://localhost:35357/v2.0', 'name': "'Identity Service'", 'id': '1' } } } def setUp(self): super(TestTemplatedCatalog, self).setUp() self.load_backends() self.load_fixtures(default_fixtures) def config_overrides(self): super(TestTemplatedCatalog, self).config_overrides() self.config_fixture.config(group='catalog', template_file=DEFAULT_CATALOG_TEMPLATES) def test_get_catalog(self): catalog_ref = self.catalog_api.get_catalog('foo', 'bar') self.assertDictEqual(catalog_ref, self.DEFAULT_FIXTURE) def test_malformed_catalog_throws_error(self): (self.catalog_api.driver.templates ['RegionOne']['compute']['adminURL']) = \ 'http://localhost:$(compute_port)s/v1.1/$(tenant)s' self.assertRaises(exception.MalformedEndpoint, self.catalog_api.get_catalog, 'fake-user', 'fake-tenant') def test_get_catalog_endpoint_disabled(self): self.skipTest("Templated backend doesn't have disabled endpoints") def test_get_v3_catalog_endpoint_disabled(self): f = (super(TestTemplatedCatalog, self). test_get_v3_catalog_endpoint_disabled) self.assertRaises(exception.NotImplemented, f) keystone-2014.1/keystone/tests/test_backend_sql.py0000664000175400017540000004647212323716272023504 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2012 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. import uuid import sqlalchemy from sqlalchemy import exc from keystone.common import sql from keystone import config from keystone import exception from keystone.identity.backends import sql as identity_sql from keystone.openstack.common.db import exception as db_exception from keystone.openstack.common.fixture import moxstubout from keystone import tests from keystone.tests import default_fixtures from keystone.tests import test_backend from keystone.token.backends import sql as token_sql CONF = config.CONF DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id class SqlTests(tests.SQLDriverOverrides, tests.TestCase): def setUp(self): super(SqlTests, self).setUp() self.load_backends() # populate the engine with tables & fixtures self.load_fixtures(default_fixtures) #defaulted by the data load self.user_foo['enabled'] = True def config_files(self): config_files = super(SqlTests, self).config_files() config_files.append(tests.dirs.tests_conf('backend_sql.conf')) return config_files class SqlModels(SqlTests): def setUp(self): super(SqlModels, self).setUp() self.metadata = sql.ModelBase.metadata self.metadata.bind = self.engine def select_table(self, name): table = sqlalchemy.Table(name, self.metadata, autoload=True) s = sqlalchemy.select([table]) return s def assertExpectedSchema(self, table, cols): table = self.select_table(table) for col, type_, length in cols: self.assertIsInstance(table.c[col].type, type_) if length: self.assertEqual(table.c[col].type.length, length) def test_user_model(self): cols = (('id', sql.String, 64), ('name', sql.String, 255), ('password', sql.String, 128), ('domain_id', sql.String, 64), ('enabled', sql.Boolean, None), ('extra', sql.JsonBlob, None)) self.assertExpectedSchema('user', cols) def test_group_model(self): cols = (('id', sql.String, 64), ('name', sql.String, 64), ('description', sql.Text, None), ('domain_id', sql.String, 64), ('extra', sql.JsonBlob, None)) self.assertExpectedSchema('group', cols) def test_domain_model(self): cols = (('id', sql.String, 64), ('name', sql.String, 64), ('enabled', sql.Boolean, None)) self.assertExpectedSchema('domain', cols) def test_project_model(self): cols = (('id', sql.String, 64), ('name', sql.String, 64), ('description', sql.Text, None), ('domain_id', sql.String, 64), ('enabled', sql.Boolean, None), ('extra', sql.JsonBlob, None)) self.assertExpectedSchema('project', cols) def test_role_model(self): cols = (('id', sql.String, 64), ('name', sql.String, 255)) self.assertExpectedSchema('role', cols) def test_role_assignment_model(self): cols = (('type', sql.Enum, None), ('actor_id', sql.String, 64), ('target_id', sql.String, 64), ('role_id', sql.String, 64), ('inherited', sql.Boolean, False)) self.assertExpectedSchema('assignment', cols) def test_user_group_membership(self): cols = (('group_id', sql.String, 64), ('user_id', sql.String, 64)) self.assertExpectedSchema('user_group_membership', cols) class SqlIdentity(SqlTests, test_backend.IdentityTests): def test_password_hashed(self): session = sql.get_session() user_ref = self.identity_api._get_user(session, self.user_foo['id']) self.assertNotEqual(user_ref['password'], self.user_foo['password']) def test_delete_user_with_project_association(self): user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} self.identity_api.create_user(user['id'], user) self.assignment_api.add_user_to_project(self.tenant_bar['id'], user['id']) self.identity_api.delete_user(user['id']) self.assertRaises(exception.UserNotFound, self.assignment_api.list_projects_for_user, user['id']) def test_create_null_user_name(self): user = {'id': uuid.uuid4().hex, 'name': None, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} self.assertRaises(exception.ValidationError, self.identity_api.create_user, user['id'], user) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, user['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user_by_name, user['name'], DEFAULT_DOMAIN_ID) def test_create_null_project_name(self): tenant = {'id': uuid.uuid4().hex, 'name': None, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.assignment_api.create_project, tenant['id'], tenant) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, tenant['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project_by_name, tenant['name'], DEFAULT_DOMAIN_ID) def test_create_null_role_name(self): role = {'id': uuid.uuid4().hex, 'name': None} self.assertRaises(exception.Conflict, self.assignment_api.create_role, role['id'], role) self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, role['id']) def test_delete_project_with_user_association(self): user = {'id': 'fake', 'name': 'fakeuser', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'passwd'} self.identity_api.create_user('fake', user) self.assignment_api.add_user_to_project(self.tenant_bar['id'], user['id']) self.assignment_api.delete_project(self.tenant_bar['id']) tenants = self.assignment_api.list_projects_for_user(user['id']) self.assertEqual(tenants, []) def test_metadata_removed_on_delete_user(self): # A test to check that the internal representation # or roles is correctly updated when a user is deleted user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'passwd'} self.identity_api.create_user(user['id'], user) role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) self.assignment_api.add_role_to_user_and_project( user['id'], self.tenant_bar['id'], role['id']) self.identity_api.delete_user(user['id']) # Now check whether the internal representation of roles # has been deleted self.assertRaises(exception.MetadataNotFound, self.assignment_api._get_metadata, user['id'], self.tenant_bar['id']) def test_metadata_removed_on_delete_project(self): # A test to check that the internal representation # or roles is correctly updated when a project is deleted user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'passwd'} self.identity_api.create_user(user['id'], user) role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) self.assignment_api.add_role_to_user_and_project( user['id'], self.tenant_bar['id'], role['id']) self.assignment_api.delete_project(self.tenant_bar['id']) # Now check whether the internal representation of roles # has been deleted self.assertRaises(exception.MetadataNotFound, self.assignment_api._get_metadata, user['id'], self.tenant_bar['id']) def test_update_project_returns_extra(self): """This tests for backwards-compatibility with an essex/folsom bug. Non-indexed attributes were returned in an 'extra' attribute, instead of on the entity itself; for consistency and backwards compatibility, those attributes should be included twice. This behavior is specific to the SQL driver. """ tenant_id = uuid.uuid4().hex arbitrary_key = uuid.uuid4().hex arbitrary_value = uuid.uuid4().hex tenant = { 'id': tenant_id, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, arbitrary_key: arbitrary_value} ref = self.assignment_api.create_project(tenant_id, tenant) self.assertEqual(arbitrary_value, ref[arbitrary_key]) self.assertIsNone(ref.get('extra')) tenant['name'] = uuid.uuid4().hex ref = self.assignment_api.update_project(tenant_id, tenant) self.assertEqual(arbitrary_value, ref[arbitrary_key]) self.assertEqual(arbitrary_value, ref['extra'][arbitrary_key]) def test_update_user_returns_extra(self): """This tests for backwards-compatibility with an essex/folsom bug. Non-indexed attributes were returned in an 'extra' attribute, instead of on the entity itself; for consistency and backwards compatibility, those attributes should be included twice. This behavior is specific to the SQL driver. """ user_id = uuid.uuid4().hex arbitrary_key = uuid.uuid4().hex arbitrary_value = uuid.uuid4().hex user = { 'id': user_id, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex, arbitrary_key: arbitrary_value} ref = self.identity_api.create_user(user_id, user) self.assertEqual(arbitrary_value, ref[arbitrary_key]) self.assertIsNone(ref.get('password')) self.assertIsNone(ref.get('extra')) user['name'] = uuid.uuid4().hex user['password'] = uuid.uuid4().hex ref = self.identity_api.update_user(user_id, user) self.assertIsNone(ref.get('password')) self.assertIsNone(ref['extra'].get('password')) self.assertEqual(arbitrary_value, ref[arbitrary_key]) self.assertEqual(arbitrary_value, ref['extra'][arbitrary_key]) def test_sql_user_to_dict_null_default_project_id(self): user_id = uuid.uuid4().hex user = { 'id': user_id, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} self.identity_api.create_user(user_id, user) session = sql.get_session() query = session.query(identity_sql.User) query = query.filter_by(id=user_id) raw_user_ref = query.one() self.assertIsNone(raw_user_ref.default_project_id) user_ref = raw_user_ref.to_dict() self.assertNotIn('default_project_id', user_ref) session.close() class SqlTrust(SqlTests, test_backend.TrustTests): pass class SqlToken(SqlTests, test_backend.TokenTests): def test_token_revocation_list_uses_right_columns(self): # This query used to be heavy with too many columns. We want # to make sure it is only running with the minimum columns # necessary. fixture = self.useFixture(moxstubout.MoxStubout()) self.mox = fixture.mox tok = token_sql.Token() session = sql.get_session() q = session.query(token_sql.TokenModel.id, token_sql.TokenModel.expires) self.mox.StubOutWithMock(session, 'query') session.query(token_sql.TokenModel.id, token_sql.TokenModel.expires).AndReturn(q) self.mox.StubOutWithMock(sql, 'get_session') sql.get_session().AndReturn(session) self.mox.ReplayAll() tok.list_revoked_tokens() def test_flush_expired_tokens_batch(self): # This test simply executes the code under test to verify # that the code is legal. It is not possible to test # whether records are deleted in batches using sqlite, # because the limit function does not seem to affect # delete subqueries; these are, however, legal. # After several failed attempts of using mox, it would # seem that the use of mock objects for testing # the target code does not seem possible, because of # the unique way the SQLAlchemy Query class's filter # method works. fixture = self.useFixture(moxstubout.MoxStubout()) self.mox = fixture.mox tok = token_sql.Token() self.mox.StubOutWithMock(tok, 'token_flush_batch_size') # Just need a batch larger than 0; note that the code # path with batch_size = 0 is covered by test_backend, # where all backends' flush_expired_tokens methods # are tested. tok.token_flush_batch_size('sqlite').AndReturn(1) self.mox.ReplayAll() tok.flush_expired_tokens() def test_token_flush_batch_size_default(self): tok = token_sql.Token() sqlite_batch = tok.token_flush_batch_size('sqlite') self.assertEqual(sqlite_batch, 0) def test_token_flush_batch_size_db2(self): tok = token_sql.Token() db2_batch = tok.token_flush_batch_size('ibm_db_sa') self.assertEqual(db2_batch, 100) class SqlCatalog(SqlTests, test_backend.CatalogTests): def test_malformed_catalog_throws_error(self): service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, } self.catalog_api.create_service(service['id'], service.copy()) malformed_url = "http://192.168.1.104:$(compute_port)s/v2/$(tenant)s" endpoint = { 'id': uuid.uuid4().hex, 'region': uuid.uuid4().hex, 'service_id': service['id'], 'interface': 'public', 'url': malformed_url, } self.catalog_api.create_endpoint(endpoint['id'], endpoint.copy()) self.assertRaises(exception.MalformedEndpoint, self.catalog_api.get_catalog, 'fake-user', 'fake-tenant') def test_get_catalog_with_empty_public_url(self): service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, } self.catalog_api.create_service(service['id'], service.copy()) endpoint = { 'id': uuid.uuid4().hex, 'region': uuid.uuid4().hex, 'interface': 'public', 'url': '', 'service_id': service['id'], } self.catalog_api.create_endpoint(endpoint['id'], endpoint.copy()) catalog = self.catalog_api.get_catalog('user', 'tenant') catalog_endpoint = catalog[endpoint['region']][service['type']] self.assertEqual(catalog_endpoint['name'], service['name']) self.assertEqual(catalog_endpoint['id'], endpoint['id']) self.assertEqual(catalog_endpoint['publicURL'], '') self.assertIsNone(catalog_endpoint.get('adminURL')) self.assertIsNone(catalog_endpoint.get('internalURL')) def test_create_endpoint_400(self): service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, } self.catalog_api.create_service(service['id'], service.copy()) endpoint = { 'id': uuid.uuid4().hex, 'region': "0" * 256, 'service_id': service['id'], 'interface': 'public', 'url': uuid.uuid4().hex, } self.assertRaises(exception.StringLengthExceeded, self.catalog_api.create_endpoint, endpoint['id'], endpoint.copy()) class SqlPolicy(SqlTests, test_backend.PolicyTests): pass class SqlInheritance(SqlTests, test_backend.InheritanceTests): pass class SqlTokenCacheInvalidation(SqlTests, test_backend.TokenCacheInvalidation): def setUp(self): super(SqlTokenCacheInvalidation, self).setUp() self._create_test_data() class SqlFilterTests(SqlTests, test_backend.FilterTests): pass class SqlLimitTests(SqlTests, test_backend.LimitTests): def setUp(self): super(SqlLimitTests, self).setUp() test_backend.LimitTests.setUp(self) class FakeTable(sql.ModelBase): __tablename__ = 'test_table' col = sql.Column(sql.String(32), primary_key=True) @sql.handle_conflicts('keystone') def insert(self): raise db_exception.DBDuplicateEntry @sql.handle_conflicts('keystone') def update(self): raise db_exception.DBError( inner_exception=exc.IntegrityError('a', 'a', 'a')) @sql.handle_conflicts('keystone') def lookup(self): raise KeyError class SqlDecorators(tests.TestCase): def test_initialization_fail(self): self.assertRaises(exception.StringLengthExceeded, FakeTable, col='a' * 64) def test_initialization(self): tt = FakeTable(col='a') self.assertEqual('a', tt.col) def test_non_ascii_init(self): # NOTE(I159): Non ASCII characters must cause UnicodeDecodeError # if encoding is not provided explicitly. self.assertRaises(UnicodeDecodeError, FakeTable, col='Я') def test_conflict_happend(self): self.assertRaises(exception.Conflict, FakeTable().insert) self.assertRaises(exception.Conflict, FakeTable().update) def test_not_conflict_error(self): self.assertRaises(KeyError, FakeTable().lookup) keystone-2014.1/keystone/tests/test_v3_federation.py0000664000175400017540000016407712323716272023770 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import random import uuid from keystone.auth import controllers as auth_controllers from keystone.common import dependency from keystone.common import serializer from keystone.common import sql from keystone.common.sql import migration_helpers from keystone import config from keystone import contrib from keystone.contrib.federation import controllers as federation_controllers from keystone.contrib.federation import utils as mapping_utils from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common import importutils from keystone.openstack.common import jsonutils from keystone.openstack.common import log from keystone.tests import mapping_fixtures from keystone.tests import test_v3 CONF = config.CONF LOG = log.getLogger(__name__) def dummy_validator(*args, **kwargs): pass @dependency.requires('federation_api') class FederationTests(test_v3.RestfulTestCase): EXTENSION_NAME = 'federation' EXTENSION_TO_ADD = 'federation_extension' def setup_database(self): super(FederationTests, self).setup_database() package_name = '.'.join((contrib.__name__, self.EXTENSION_NAME)) package = importutils.import_module(package_name) abs_path = migration_helpers.find_migrate_repo(package) migration.db_version_control(sql.get_engine(), abs_path) migration.db_sync(sql.get_engine(), abs_path) class FederatedIdentityProviderTests(FederationTests): """A test class for Identity Providers.""" idp_keys = ['description', 'enabled'] default_body = {'description': None, 'enabled': True} def base_url(self, suffix=None): if suffix is not None: return '/OS-FEDERATION/identity_providers/' + str(suffix) return '/OS-FEDERATION/identity_providers' def _fetch_attribute_from_response(self, resp, parameter, assert_is_not_none=True): """Fetch single attribute from TestResponse object.""" result = resp.result.get(parameter) if assert_is_not_none: self.assertIsNotNone(result) return result def _create_and_decapsulate_response(self, body=None): """Create IdP and fetch it's random id along with entity.""" default_resp = self._create_default_idp(body=body) idp = self._fetch_attribute_from_response(default_resp, 'identity_provider') self.assertIsNotNone(idp) idp_id = idp.get('id') return (idp_id, idp) def _get_idp(self, idp_id): """Fetch IdP entity based on it's id.""" url = self.base_url(suffix=idp_id) resp = self.get(url) return resp def _create_default_idp(self, body=None): """Create default IdP.""" url = self.base_url(suffix=uuid.uuid4().hex) if body is None: body = self._http_idp_input() resp = self.put(url, body={'identity_provider': body}, expected_status=201) return resp def _http_idp_input(self, **kwargs): """Create default input for IdP data.""" body = None if 'body' not in kwargs: body = self.default_body.copy() body['description'] = uuid.uuid4().hex else: body = kwargs['body'] return body def _assign_protocol_to_idp(self, idp_id=None, proto=None, url=None, mapping_id=None, validate=True, **kwargs): if url is None: url = self.base_url(suffix='%(idp_id)s/protocols/%(protocol_id)s') if idp_id is None: idp_id, _ = self._create_and_decapsulate_response() if proto is None: proto = uuid.uuid4().hex if mapping_id is None: mapping_id = uuid.uuid4().hex body = {'mapping_id': mapping_id} url = url % {'idp_id': idp_id, 'protocol_id': proto} resp = self.put(url, body={'protocol': body}, **kwargs) if validate: self.assertValidResponse(resp, 'protocol', dummy_validator, keys_to_check=['id', 'mapping_id'], ref={'id': proto, 'mapping_id': mapping_id}) return (resp, idp_id, proto) def _get_protocol(self, idp_id, protocol_id): url = "%s/protocols/%s" % (idp_id, protocol_id) url = self.base_url(suffix=url) r = self.get(url) return r def test_create_idp(self): """Creates the IdentityProvider entity.""" keys_to_check = self.idp_keys body = self._http_idp_input() resp = self._create_default_idp(body=body) self.assertValidResponse(resp, 'identity_provider', dummy_validator, keys_to_check=keys_to_check, ref=body) def test_list_idps(self, iterations=5): """Lists all available IdentityProviders. This test collects ids of created IdPs and intersects it with the list of all available IdPs. List of all IdPs can be a superset of IdPs created in this test, because other tests also create IdPs. """ def get_id(resp): r = self._fetch_attribute_from_response(resp, 'identity_provider') return r.get('id') ids = [] for _ in range(iterations): id = get_id(self._create_default_idp()) ids.append(id) ids = set(ids) keys_to_check = self.idp_keys url = self.base_url() resp = self.get(url) self.assertValidListResponse(resp, 'identity_providers', dummy_validator, keys_to_check=keys_to_check) entities = self._fetch_attribute_from_response(resp, 'identity_providers') entities_ids = set([e['id'] for e in entities]) ids_intersection = entities_ids.intersection(ids) self.assertEqual(ids_intersection, ids) def test_check_idp_uniqueness(self): """Add same IdP twice. Expect HTTP 409 code for the latter call. """ url = self.base_url(suffix=uuid.uuid4().hex) body = self._http_idp_input() self.put(url, body={'identity_provider': body}, expected_status=201) self.put(url, body={'identity_provider': body}, expected_status=409) def test_get_idp(self): """Create and later fetch IdP.""" body = self._http_idp_input() default_resp = self._create_default_idp(body=body) default_idp = self._fetch_attribute_from_response(default_resp, 'identity_provider') idp_id = default_idp.get('id') url = self.base_url(suffix=idp_id) resp = self.get(url) self.assertValidResponse(resp, 'identity_provider', dummy_validator, keys_to_check=body.keys(), ref=body) def test_get_nonexisting_idp(self): """Fetch nonexisting IdP entity. Expected HTTP 404 status code. """ idp_id = uuid.uuid4().hex self.assertIsNotNone(idp_id) url = self.base_url(suffix=idp_id) self.get(url, expected_status=404) def test_delete_existing_idp(self): """Create and later delete IdP. Expect HTTP 404 for the GET IdP call. """ default_resp = self._create_default_idp() default_idp = self._fetch_attribute_from_response(default_resp, 'identity_provider') idp_id = default_idp.get('id') self.assertIsNotNone(idp_id) url = self.base_url(suffix=idp_id) self.delete(url) self.get(url, expected_status=404) def test_delete_nonexisting_idp(self): """Delete nonexisting IdP. Expect HTTP 404 for the GET IdP call. """ idp_id = uuid.uuid4().hex url = self.base_url(suffix=idp_id) self.delete(url, expected_status=404) def test_update_idp_mutable_attributes(self): """Update IdP's mutable parameters.""" default_resp = self._create_default_idp() default_idp = self._fetch_attribute_from_response(default_resp, 'identity_provider') idp_id = default_idp.get('id') url = self.base_url(suffix=idp_id) self.assertIsNotNone(idp_id) _enabled = not default_idp.get('enabled') body = {'description': uuid.uuid4().hex, 'enabled': _enabled} body = {'identity_provider': body} resp = self.patch(url, body=body) updated_idp = self._fetch_attribute_from_response(resp, 'identity_provider') body = body['identity_provider'] for key in body.keys(): self.assertEqual(body[key], updated_idp.get(key)) resp = self.get(url) updated_idp = self._fetch_attribute_from_response(resp, 'identity_provider') for key in body.keys(): self.assertEqual(body[key], updated_idp.get(key)) def test_update_idp_immutable_attributes(self): """Update IdP's immutable parameters. Expect HTTP 403 code. """ default_resp = self._create_default_idp() default_idp = self._fetch_attribute_from_response(default_resp, 'identity_provider') idp_id = default_idp.get('id') self.assertIsNotNone(idp_id) body = self._http_idp_input() body['id'] = uuid.uuid4().hex body['protocols'] = [uuid.uuid4().hex, uuid.uuid4().hex] url = self.base_url(suffix=idp_id) self.patch(url, body={'identity_provider': body}, expected_status=403) def test_update_nonexistent_idp(self): """Update nonexistent IdP Expect HTTP 404 code. """ idp_id = uuid.uuid4().hex url = self.base_url(suffix=idp_id) body = self._http_idp_input() body['enabled'] = False body = {'identity_provider': body} self.patch(url, body=body, expected_status=404) def test_assign_protocol_to_idp(self): """Assign a protocol to existing IdP.""" self._assign_protocol_to_idp(expected_status=201) def test_protocol_composite_pk(self): """Test whether Keystone let's add two entities with identical names, however attached to different IdPs. 1. Add IdP and assign it protocol with predefined name 2. Add another IdP and assign it a protocol with same name. Expect HTTP 201 code """ url = self.base_url(suffix='%(idp_id)s/protocols/%(protocol_id)s') kwargs = {'expected_status': 201} self._assign_protocol_to_idp(proto='saml2', url=url, **kwargs) self._assign_protocol_to_idp(proto='saml2', url=url, **kwargs) def test_protocol_idp_pk_uniqueness(self): """Test whether Keystone checks for unique idp/protocol values. Add same protocol twice, expect Keystone to reject a latter call and return HTTP 409 code. """ url = self.base_url(suffix='%(idp_id)s/protocols/%(protocol_id)s') kwargs = {'expected_status': 201} resp, idp_id, proto = self._assign_protocol_to_idp(proto='saml2', url=url, **kwargs) kwargs = {'expected_status': 409} resp, idp_id, proto = self._assign_protocol_to_idp(idp_id=idp_id, proto='saml2', validate=False, url=url, **kwargs) def test_assign_protocol_to_nonexistent_idp(self): """Assign protocol to IdP that doesn't exist. Expect HTTP 404 code. """ idp_id = uuid.uuid4().hex kwargs = {'expected_status': 404} self._assign_protocol_to_idp(proto='saml2', idp_id=idp_id, validate=False, **kwargs) def test_get_protocol(self): """Create and later fetch protocol tied to IdP.""" resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201) proto_id = self._fetch_attribute_from_response(resp, 'protocol')['id'] url = "%s/protocols/%s" % (idp_id, proto_id) url = self.base_url(suffix=url) resp = self.get(url) reference = {'id': proto_id} self.assertValidResponse(resp, 'protocol', dummy_validator, keys_to_check=reference.keys(), ref=reference) def test_list_protocols(self): """Create set of protocols and later list them. Compare input and output id sets. """ resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201) iterations = random.randint(0, 16) protocol_ids = [] for _ in range(iterations): resp, _, proto = self._assign_protocol_to_idp(idp_id=idp_id, expected_status=201) proto_id = self._fetch_attribute_from_response(resp, 'protocol') proto_id = proto_id['id'] protocol_ids.append(proto_id) url = "%s/protocols" % idp_id url = self.base_url(suffix=url) resp = self.get(url) self.assertValidListResponse(resp, 'protocols', dummy_validator, keys_to_check=['id']) entities = self._fetch_attribute_from_response(resp, 'protocols') entities = set([entity['id'] for entity in entities]) protocols_intersection = entities.intersection(protocol_ids) self.assertEqual(protocols_intersection, set(protocol_ids)) def test_update_protocols_attribute(self): """Update protocol's attribute.""" resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201) new_mapping_id = uuid.uuid4().hex url = "%s/protocols/%s" % (idp_id, proto) url = self.base_url(suffix=url) body = {'mapping_id': new_mapping_id} resp = self.patch(url, body={'protocol': body}) self.assertValidResponse(resp, 'protocol', dummy_validator, keys_to_check=['id', 'mapping_id'], ref={'id': proto, 'mapping_id': new_mapping_id} ) def test_delete_protocol(self): """Delete protocol. Expect HTTP 404 code for the GET call after the protocol is deleted. """ url = self.base_url(suffix='/%(idp_id)s/' 'protocols/%(protocol_id)s') resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201) url = url % {'idp_id': idp_id, 'protocol_id': proto} self.delete(url) self.get(url, expected_status=404) class MappingCRUDTests(FederationTests): """A class for testing CRUD operations for Mappings.""" MAPPING_URL = '/OS-FEDERATION/mappings/' def assertValidMappingListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'mappings', self.assertValidMapping, keys_to_check=[], *args, **kwargs) def assertValidMappingResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'mapping', self.assertValidMapping, keys_to_check=[], *args, **kwargs) def assertValidMapping(self, entity, ref=None): self.assertIsNotNone(entity.get('id')) self.assertIsNotNone(entity.get('rules')) if ref: self.assertEqual(jsonutils.loads(entity['rules']), ref['rules']) return entity def _create_default_mapping_entry(self): url = self.MAPPING_URL + uuid.uuid4().hex resp = self.put(url, body={'mapping': mapping_fixtures.MAPPING_LARGE}, expected_status=201) return resp def _get_id_from_response(self, resp): r = resp.result.get('mapping') return r.get('id') def test_mapping_create(self): resp = self._create_default_mapping_entry() self.assertValidMappingResponse(resp, mapping_fixtures.MAPPING_LARGE) def test_mapping_list(self): url = self.MAPPING_URL self._create_default_mapping_entry() resp = self.get(url) entities = resp.result.get('mappings') self.assertIsNotNone(entities) self.assertResponseStatus(resp, 200) self.assertValidListLinks(resp.result.get('links')) self.assertEqual(len(entities), 1) def test_mapping_delete(self): url = self.MAPPING_URL + '%(mapping_id)s' resp = self._create_default_mapping_entry() mapping_id = self._get_id_from_response(resp) url = url % {'mapping_id': str(mapping_id)} resp = self.delete(url) self.assertResponseStatus(resp, 204) self.get(url, expected_status=404) def test_mapping_get(self): url = self.MAPPING_URL + '%(mapping_id)s' resp = self._create_default_mapping_entry() mapping_id = self._get_id_from_response(resp) url = url % {'mapping_id': mapping_id} resp = self.get(url) self.assertValidMappingResponse(resp, mapping_fixtures.MAPPING_LARGE) def test_mapping_update(self): url = self.MAPPING_URL + '%(mapping_id)s' resp = self._create_default_mapping_entry() mapping_id = self._get_id_from_response(resp) url = url % {'mapping_id': mapping_id} resp = self.patch(url, body={'mapping': mapping_fixtures.MAPPING_SMALL}) self.assertValidMappingResponse(resp, mapping_fixtures.MAPPING_SMALL) resp = self.get(url) self.assertValidMappingResponse(resp, mapping_fixtures.MAPPING_SMALL) def test_delete_mapping_dne(self): url = self.MAPPING_URL + uuid.uuid4().hex self.delete(url, expected_status=404) def test_get_mapping_dne(self): url = self.MAPPING_URL + uuid.uuid4().hex self.get(url, expected_status=404) def test_create_mapping_bad_requirements(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_BAD_REQ}) def test_create_mapping_no_rules(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_NO_RULES}) def test_create_mapping_no_remote_objects(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_NO_REMOTE}) def test_create_mapping_bad_value(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_BAD_VALUE}) def test_create_mapping_missing_local(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_MISSING_LOCAL}) def test_create_mapping_missing_type(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_MISSING_TYPE}) def test_create_mapping_wrong_type(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_WRONG_TYPE}) def test_create_mapping_extra_remote_properties_not_any_of(self): url = self.MAPPING_URL + uuid.uuid4().hex mapping = mapping_fixtures.MAPPING_EXTRA_REMOTE_PROPS_NOT_ANY_OF self.put(url, expected_status=400, body={'mapping': mapping}) def test_create_mapping_extra_remote_properties_any_one_of(self): url = self.MAPPING_URL + uuid.uuid4().hex mapping = mapping_fixtures.MAPPING_EXTRA_REMOTE_PROPS_ANY_ONE_OF self.put(url, expected_status=400, body={'mapping': mapping}) def test_create_mapping_extra_remote_properties_just_type(self): url = self.MAPPING_URL + uuid.uuid4().hex mapping = mapping_fixtures.MAPPING_EXTRA_REMOTE_PROPS_JUST_TYPE self.put(url, expected_status=400, body={'mapping': mapping}) def test_create_mapping_empty_map(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': {}}) def test_create_mapping_extra_rules_properties(self): url = self.MAPPING_URL + uuid.uuid4().hex self.put(url, expected_status=400, body={'mapping': mapping_fixtures.MAPPING_EXTRA_RULES_PROPS}) class MappingRuleEngineTests(FederationTests): """A class for testing the mapping rule engine.""" def test_rule_engine_any_one_of_and_direct_mapping(self): """Should return user's name and group id EMPLOYEE_GROUP_ID. The ADMIN_ASSERTION should successfully have a match in MAPPING_LARGE. The will test the case where `any_one_of` is valid, and there is a direct mapping for the users name. """ mapping = mapping_fixtures.MAPPING_LARGE assertion = mapping_fixtures.ADMIN_ASSERTION rp = mapping_utils.RuleProcessor(mapping['rules']) values = rp.process(assertion) fn = assertion.get('FirstName') ln = assertion.get('LastName') full_name = '%s %s' % (fn, ln) group_ids = values.get('group_ids') name = values.get('name') self.assertIn(mapping_fixtures.EMPLOYEE_GROUP_ID, group_ids) self.assertEqual(name, full_name) def test_rule_engine_no_regex_match(self): """Should deny authorization, the email of the tester won't match. This will not match since the email in the assertion will fail the regex test. It is set to match any @example.com address. But the incoming value is set to eviltester@example.org. RuleProcessor should raise exception.Unauthorized exception. """ mapping = mapping_fixtures.MAPPING_LARGE assertion = mapping_fixtures.BAD_TESTER_ASSERTION rp = mapping_utils.RuleProcessor(mapping['rules']) self.assertRaises(exception.Unauthorized, rp.process, assertion) def test_rule_engine_any_one_of_many_rules(self): """Should return group CONTRACTOR_GROUP_ID. The CONTRACTOR_ASSERTION should successfully have a match in MAPPING_SMALL. This will test the case where many rules must be matched, including an `any_one_of`, and a direct mapping. """ mapping = mapping_fixtures.MAPPING_SMALL assertion = mapping_fixtures.CONTRACTOR_ASSERTION rp = mapping_utils.RuleProcessor(mapping['rules']) values = rp.process(assertion) user_name = assertion.get('UserName') group_ids = values.get('group_ids') name = values.get('name') self.assertEqual(user_name, name) self.assertIn(mapping_fixtures.CONTRACTOR_GROUP_ID, group_ids) def test_rule_engine_not_any_of_and_direct_mapping(self): """Should return user's name and email. The CUSTOMER_ASSERTION should successfully have a match in MAPPING_LARGE. This will test the case where a requirement has `not_any_of`, and direct mapping to a username, no group. """ mapping = mapping_fixtures.MAPPING_LARGE assertion = mapping_fixtures.CUSTOMER_ASSERTION rp = mapping_utils.RuleProcessor(mapping['rules']) values = rp.process(assertion) user_name = assertion.get('UserName') group_ids = values.get('group_ids') name = values.get('name') self.assertEqual(name, user_name) self.assertEqual(group_ids, []) def test_rule_engine_not_any_of_many_rules(self): """Should return group EMPLOYEE_GROUP_ID. The EMPLOYEE_ASSERTION should successfully have a match in MAPPING_SMALL. This will test the case where many remote rules must be matched, including a `not_any_of`. """ mapping = mapping_fixtures.MAPPING_SMALL assertion = mapping_fixtures.EMPLOYEE_ASSERTION rp = mapping_utils.RuleProcessor(mapping['rules']) values = rp.process(assertion) user_name = assertion.get('UserName') group_ids = values.get('group_ids') name = values.get('name') self.assertEqual(name, user_name) self.assertIn(mapping_fixtures.EMPLOYEE_GROUP_ID, group_ids) def _rule_engine_regex_match_and_many_groups(self, assertion): """Should return group DEVELOPER_GROUP_ID and TESTER_GROUP_ID. A helper function injecting assertion passed as an argument. Expect DEVELOPER_GROUP_ID and TESTER_GROUP_ID in the results. """ mapping = mapping_fixtures.MAPPING_LARGE rp = mapping_utils.RuleProcessor(mapping['rules']) values = rp.process(assertion) user_name = assertion.get('UserName') group_ids = values.get('group_ids') name = values.get('name') self.assertEqual(user_name, name) self.assertIn(mapping_fixtures.DEVELOPER_GROUP_ID, group_ids) self.assertIn(mapping_fixtures.TESTER_GROUP_ID, group_ids) def test_rule_engine_regex_match_and_many_groups(self): """Should return group DEVELOPER_GROUP_ID and TESTER_GROUP_ID. The TESTER_ASSERTION should successfully have a match in MAPPING_LARGE. This will test a successful regex match for an `any_one_of` evaluation type, and will have many groups returned. """ self._rule_engine_regex_match_and_many_groups( mapping_fixtures.TESTER_ASSERTION) def test_rule_engine_discards_nonstring_objects(self): """Check whether RuleProcessor discards non string objects. Despite the fact that assertion is malformed and contains non string objects, RuleProcessor should correctly discard them and successfully have a match in MAPPING_LARGE. """ self._rule_engine_regex_match_and_many_groups( mapping_fixtures.MALFORMED_TESTER_ASSERTION) def test_rule_engine_fails_after_discarding_nonstring(self): """Check whether RuleProcessor discards non string objects. Expect RuleProcessor to discard non string object, which is required for a correct rule match. Since no rules are matched expect RuleProcessor to raise exception.Unauthorized exception. """ mapping = mapping_fixtures.MAPPING_SMALL rp = mapping_utils.RuleProcessor(mapping['rules']) assertion = mapping_fixtures.CONTRACTOR_MALFORMED_ASSERTION self.assertRaises(exception.Unauthorized, rp.process, assertion) class FederatedTokenTests(FederationTests): IDP = 'ORG_IDP' PROTOCOL = 'saml2' AUTH_METHOD = 'saml2' USER = 'user@ORGANIZATION' ASSERTION_PREFIX = 'PREFIX_' UNSCOPED_V3_SAML2_REQ = { "identity": { "methods": [AUTH_METHOD], AUTH_METHOD: { "identity_provider": IDP, "protocol": PROTOCOL } } } AUTH_URL = '/auth/tokens' def setUp(self): super(FederationTests, self).setUp() self.load_sample_data() self.load_federation_sample_data() def idp_ref(self, id=None): idp = { 'id': id or uuid.uuid4().hex, 'enabled': True, 'description': uuid.uuid4().hex } return idp def proto_ref(self, mapping_id=None): proto = { 'id': uuid.uuid4().hex, 'mapping_id': mapping_id or uuid.uuid4().hex } return proto def mapping_ref(self, rules=None): return { 'id': uuid.uuid4().hex, 'rules': rules or self.rules['rules'] } def _assertSerializeToXML(self, json_body): """Serialize JSON body to XML. Serialize JSON body to XML, then deserialize to JSON again. Expect both JSON dictionaries to be equal. """ xml_body = serializer.to_xml(json_body) json_deserialized = serializer.from_xml(xml_body) self.assertDictEqual(json_deserialized, json_body) def _scope_request(self, unscoped_token_id, scope, scope_id): return { 'auth': { 'identity': { 'methods': [ self.AUTH_METHOD ], self.AUTH_METHOD: { 'id': unscoped_token_id } }, 'scope': { scope: { 'id': scope_id } } } } def _project(self, project): return (project['id'], project['name']) def _roles(self, roles): return set([(r['id'], r['name']) for r in roles]) def _check_projects_and_roles(self, token, roles, projects): """Check whether the projects and the roles match.""" token_roles = token.get('roles') if token_roles is None: raise AssertionError('Roles not found in the token') token_roles = self._roles(token_roles) roles_ref = self._roles(roles) self.assertEqual(token_roles, roles_ref) token_projects = token.get('project') if token_projects is None: raise AssertionError('Projects not found in the token') token_projects = self._project(token_projects) projects_ref = self._project(projects) self.assertEqual(token_projects, projects_ref) def _check_scoped_token_attributes(self, token): def xor_project_domain(iterable): return sum(('project' in iterable, 'domain' in iterable)) % 2 for obj in ('user', 'catalog', 'expires_at', 'issued_at', 'methods', 'roles'): self.assertIn(obj, token) # Check for either project or domain if not xor_project_domain(token.keys()): raise AssertionError("You must specify either" "project or domain.") def _issue_unscoped_token(self, assertion='EMPLOYEE_ASSERTION'): api = federation_controllers.Auth() context = {'environment': {}} self._inject_assertion(context, assertion) r = api.federated_authentication(context, self.IDP, self.PROTOCOL) return r def test_issue_unscoped_token(self): r = self._issue_unscoped_token() self.assertIsNotNone(r.headers.get('X-Subject-Token')) def test_issue_unscoped_token_serialize_to_xml(self): """Issue unscoped token and serialize to XML. Make sure common.serializer doesn't complain about the response structure and tag names. """ r = self._issue_unscoped_token() token_resp = r.json_body # Remove 'extras' if empty or None, # as JSON and XML (de)serializers treat # them differently, making dictionaries # comparisions fail. if not token_resp['token'].get('extras'): token_resp['token'].pop('extras') self._assertSerializeToXML(token_resp) def test_issue_unscoped_token_no_groups(self): self.assertRaises(exception.Unauthorized, self._issue_unscoped_token, assertion='BAD_TESTER_ASSERTION') def test_issue_unscoped_token_malformed_environment(self): """Test whether non string objects are filtered out. Put non string objects into the environment, inject correct assertion and try to get an unscoped token. Expect server not to fail on using split() method on non string objects and return token id in the HTTP header. """ api = auth_controllers.Auth() context = { 'environment': { 'malformed_object': object(), 'another_bad_idea': tuple(xrange(10)), 'yet_another_bad_param': dict(zip(uuid.uuid4().hex, range(32))) } } self._inject_assertion(context, 'EMPLOYEE_ASSERTION') r = api.authenticate_for_token(context, self.UNSCOPED_V3_SAML2_REQ) self.assertIsNotNone(r.headers.get('X-Subject-Token')) def test_scope_to_project_once(self): r = self.post(self.AUTH_URL, body=self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_EMPLOYEE) token_resp = r.result['token'] project_id = token_resp['project']['id'] self.assertEqual(project_id, self.proj_employees['id']) self._check_scoped_token_attributes(token_resp) roles_ref = [self.role_employee] projects_ref = self.proj_employees self._check_projects_and_roles(token_resp, roles_ref, projects_ref) def test_scope_to_bad_project(self): """Scope unscoped token with a project we don't have access to.""" self.post(self.AUTH_URL, body=self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_CUSTOMER, expected_status=401) def test_scope_to_project_multiple_times(self): """Try to scope the unscoped token multiple times. The new tokens should be scoped to: * Customers' project * Employees' project """ bodies = (self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_ADMIN, self.TOKEN_SCOPE_PROJECT_CUSTOMER_FROM_ADMIN) project_ids = (self.proj_employees['id'], self.proj_customers['id']) for body, project_id_ref in zip(bodies, project_ids): r = self.post(self.AUTH_URL, body=body) token_resp = r.result['token'] project_id = token_resp['project']['id'] self.assertEqual(project_id, project_id_ref) self._check_scoped_token_attributes(token_resp) def test_scope_token_from_nonexistent_unscoped_token(self): """Try to scope token from non-existent unscoped token.""" self.post(self.AUTH_URL, body=self.TOKEN_SCOPE_PROJECT_FROM_NONEXISTENT_TOKEN, expected_status=404) def test_issue_token_from_rules_without_user(self): api = auth_controllers.Auth() context = {'environment': {}} self._inject_assertion(context, 'BAD_TESTER_ASSERTION') self.assertRaises(exception.Unauthorized, api.authenticate_for_token, context, self.UNSCOPED_V3_SAML2_REQ) def test_issue_token_with_nonexistent_group(self): """Inject assertion that matches rule issuing bad group id. Expect server to find out that some groups are missing in the backend and raise exception.MappedGroupNotFound exception. """ self.assertRaises(exception.MappedGroupNotFound, self._issue_unscoped_token, assertion='CONTRACTOR_ASSERTION') def test_scope_to_domain_once(self): r = self.post(self.AUTH_URL, body=self.TOKEN_SCOPE_DOMAIN_A_FROM_CUSTOMER) token_resp = r.result['token'] domain_id = token_resp['domain']['id'] self.assertEqual(domain_id, self.domainA['id']) self._check_scoped_token_attributes(token_resp) def test_scope_to_domain_multiple_tokens(self): """Issue multiple tokens scoping to different domains. The new tokens should be scoped to: * domainA * domainB * domainC """ bodies = (self.TOKEN_SCOPE_DOMAIN_A_FROM_ADMIN, self.TOKEN_SCOPE_DOMAIN_B_FROM_ADMIN, self.TOKEN_SCOPE_DOMAIN_C_FROM_ADMIN) domain_ids = (self.domainA['id'], self.domainB['id'], self.domainC['id']) for body, domain_id_ref in zip(bodies, domain_ids): r = self.post(self.AUTH_URL, body=body) token_resp = r.result['token'] domain_id = token_resp['domain']['id'] self.assertEqual(domain_id, domain_id_ref) self._check_scoped_token_attributes(token_resp) def test_list_projects(self): url = '/OS-FEDERATION/projects' token = (self.tokens['CUSTOMER_ASSERTION'], self.tokens['EMPLOYEE_ASSERTION'], self.tokens['ADMIN_ASSERTION']) projects_refs = (set([self.proj_customers['id']]), set([self.proj_employees['id'], self.project_all['id']]), set([self.proj_employees['id'], self.project_all['id'], self.proj_customers['id']])) for token, projects_ref in zip(token, projects_refs): r = self.get(url, token=token) projects_resp = r.result['projects'] projects = set(p['id'] for p in projects_resp) self.assertEqual(projects, projects_ref) def test_list_domains(self): url = '/OS-FEDERATION/domains' tokens = (self.tokens['CUSTOMER_ASSERTION'], self.tokens['EMPLOYEE_ASSERTION'], self.tokens['ADMIN_ASSERTION']) domain_refs = (set([self.domainA['id']]), set([self.domainA['id'], self.domainB['id']]), set([self.domainA['id'], self.domainB['id'], self.domainC['id']])) for token, domains_ref in zip(tokens, domain_refs): r = self.get(url, token=token) domains_resp = r.result['domains'] domains = set(p['id'] for p in domains_resp) self.assertEqual(domains, domains_ref) def test_full_workflow(self): """Test 'standard' workflow for granting access tokens. * Issue unscoped token * List available projects based on groups * Scope token to a one of available projects """ r = self._issue_unscoped_token() employee_unscoped_token_id = r.headers.get('X-Subject-Token') r = self.get('/OS-FEDERATION/projects', token=employee_unscoped_token_id) projects = r.result['projects'] random_project = random.randint(0, len(projects)) - 1 project = projects[random_project] v3_scope_request = self._scope_request(employee_unscoped_token_id, 'project', project['id']) r = self.post(self.AUTH_URL, body=v3_scope_request) token_resp = r.result['token'] project_id = token_resp['project']['id'] self.assertEqual(project_id, project['id']) self._check_scoped_token_attributes(token_resp) def test_workflow_with_groups_deletion(self): """Test full workflow with groups deletion before token scoping. The test scenario is as follows: - Create group ``group`` - Create and assign roles to ``group`` and ``project_all`` - Patch mapping rules for existing IdP so it issues group id - Issue unscoped token with ``group``'s id - Delete group ``group`` - Scope token to ``project_all`` - Expect HTTP 500 response """ # create group and role group = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(group['id'], group) role = self.new_role_ref() self.assignment_api.create_role(role['id'], role) # assign role to group and project_admins self.assignment_api.create_grant(role['id'], group_id=group['id'], project_id=self.project_all['id']) rules = { 'rules': [ { 'local': [ { 'group': { 'id': group['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'LastName', 'any_one_of': [ 'Account' ] } ] } ] } self.federation_api.update_mapping(self.mapping['id'], rules) r = self._issue_unscoped_token(assertion='TESTER_ASSERTION') token_id = r.headers.get('X-Subject-Token') # delete group self.identity_api.delete_group(group['id']) # scope token to project_all, expect HTTP 500 scoped_token = self._scope_request( token_id, 'project', self.project_all['id']) self.post(self.AUTH_URL, body=scoped_token, expected_status=500) def test_assertion_prefix_parameter(self): """Test parameters filtering based on the prefix. With ``assertion_prefix`` set to fixed, non defailt value, issue an unscoped token from assertion EMPLOYEE_ASSERTION_PREFIXED. Expect server to return unscoped token. """ self.config_fixture.config(group='federation', assertion_prefix=self.ASSERTION_PREFIX) r = self._issue_unscoped_token(assertion='EMPLOYEE_ASSERTION_PREFIXED') self.assertIsNotNone(r.headers.get('X-Subject-Token')) def test_assertion_prefix_parameter_expect_fail(self): """Test parameters filtering based on the prefix. With ``assertion_prefix`` default value set to empty string issue an unscoped token from assertion EMPLOYEE_ASSERTION. Next, configure ``assertion_prefix`` to value ``UserName``. Try issuing unscoped token with EMPLOYEE_ASSERTION. Expect server to raise exception.Unathorized exception. """ r = self._issue_unscoped_token() self.assertIsNotNone(r.headers.get('X-Subject-Token')) self.config_fixture.config(group='federation', assertion_prefix='UserName') self.assertRaises(exception.Unauthorized, self._issue_unscoped_token) def load_federation_sample_data(self): """Inject additional data.""" # Create and add domains self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.domainC = self.new_domain_ref() self.assignment_api.create_domain(self.domainC['id'], self.domainC) # Create and add projects self.proj_employees = self.new_project_ref( domain_id=self.domainA['id']) self.assignment_api.create_project(self.proj_employees['id'], self.proj_employees) self.proj_customers = self.new_project_ref( domain_id=self.domainA['id']) self.assignment_api.create_project(self.proj_customers['id'], self.proj_customers) self.project_all = self.new_project_ref( domain_id=self.domainA['id']) self.assignment_api.create_project(self.project_all['id'], self.project_all) # Create and add groups self.group_employees = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group_employees['id'], self.group_employees) self.group_customers = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group_customers['id'], self.group_customers) self.group_admins = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group_admins['id'], self.group_admins) # Create and add roles self.role_employee = self.new_role_ref() self.assignment_api.create_role(self.role_employee['id'], self.role_employee) self.role_customer = self.new_role_ref() self.assignment_api.create_role(self.role_customer['id'], self.role_customer) self.role_admin = self.new_role_ref() self.assignment_api.create_role(self.role_admin['id'], self.role_admin) # Employees can access # * proj_employees # * project_all self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], project_id=self.proj_employees['id']) self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], project_id=self.project_all['id']) # Customers can access # * proj_customers self.assignment_api.create_grant(self.role_customer['id'], group_id=self.group_customers['id'], project_id=self.proj_customers['id']) # Admins can access: # * proj_customers # * proj_employees # * project_all self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], project_id=self.proj_customers['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], project_id=self.proj_employees['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], project_id=self.project_all['id']) self.assignment_api.create_grant(self.role_customer['id'], group_id=self.group_customers['id'], domain_id=self.domainA['id']) # Customers can access: # * domain A self.assignment_api.create_grant(self.role_customer['id'], group_id=self.group_customers['id'], domain_id=self.domainA['id']) # Employees can access: # * domain A # * domain B self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role_employee['id'], group_id=self.group_employees['id'], domain_id=self.domainB['id']) # Admins can access: # * domain A # * domain B # * domain C self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], domain_id=self.domainB['id']) self.assignment_api.create_grant(self.role_admin['id'], group_id=self.group_admins['id'], domain_id=self.domainC['id']) self.rules = { 'rules': [ { 'local': [ { 'group': { 'id': self.group_employees['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'orgPersonType', 'any_one_of': [ 'Employee' ] } ] }, { 'local': [ { 'group': { 'id': self.group_employees['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': self.ASSERTION_PREFIX + 'UserName' }, { 'type': self.ASSERTION_PREFIX + 'orgPersonType', 'any_one_of': [ 'SuperEmployee' ] } ] }, { 'local': [ { 'group': { 'id': self.group_customers['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'orgPersonType', 'any_one_of': [ 'Customer' ] } ] }, { 'local': [ { 'group': { 'id': self.group_admins['id'] } }, { 'group': { 'id': self.group_employees['id'] } }, { 'group': { 'id': self.group_customers['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName' }, { 'type': 'orgPersonType', 'any_one_of': [ 'Admin', 'Chief' ] } ] }, { 'local': [ { 'group': { 'id': uuid.uuid4().hex } }, { 'group': { 'id': self.group_customers['id'] } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName', }, { 'type': 'FirstName', 'any_one_of': [ 'Jill' ] }, { 'type': 'LastName', 'any_one_of': [ 'Smith' ] } ] }, { 'local': [ { 'group': { 'id': 'this_group_no_longer_exists' } }, { 'user': { 'name': '{0}' } } ], 'remote': [ { 'type': 'UserName', }, { 'type': 'Email', 'any_one_of': [ 'testacct@example.com' ] }, { 'type': 'orgPersonType', 'any_one_of': [ 'Tester' ] } ] }, ] } # Add IDP self.idp = self.idp_ref(id=self.IDP) self.federation_api.create_idp(self.idp['id'], self.idp) # Add a mapping self.mapping = self.mapping_ref() self.federation_api.create_mapping(self.mapping['id'], self.mapping) # Add protocols self.proto_saml = self.proto_ref(mapping_id=self.mapping['id']) self.proto_saml['id'] = self.PROTOCOL self.federation_api.create_protocol(self.idp['id'], self.proto_saml['id'], self.proto_saml) # Generate fake tokens context = {'environment': {}} self.tokens = {} VARIANTS = ('EMPLOYEE_ASSERTION', 'CUSTOMER_ASSERTION', 'ADMIN_ASSERTION') api = auth_controllers.Auth() for variant in VARIANTS: self._inject_assertion(context, variant) r = api.authenticate_for_token(context, self.UNSCOPED_V3_SAML2_REQ) self.tokens[variant] = r.headers.get('X-Subject-Token') self.TOKEN_SCOPE_PROJECT_FROM_NONEXISTENT_TOKEN = self._scope_request( uuid.uuid4().hex, 'project', self.proj_customers['id']) self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_EMPLOYEE = self._scope_request( self.tokens['EMPLOYEE_ASSERTION'], 'project', self.proj_employees['id']) self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'project', self.proj_employees['id']) self.TOKEN_SCOPE_PROJECT_CUSTOMER_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'project', self.proj_customers['id']) self.TOKEN_SCOPE_PROJECT_EMPLOYEE_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'project', self.proj_employees['id']) self.TOKEN_SCOPE_DOMAIN_A_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'domain', self.domainA['id']) self.TOKEN_SCOPE_DOMAIN_B_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'domain', self.domainB['id']) self.TOKEN_SCOPE_DOMAIN_B_FROM_CUSTOMER = self._scope_request( self.tokens['CUSTOMER_ASSERTION'], 'domain', self.domainB['id']) self.TOKEN_SCOPE_DOMAIN_A_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'domain', self.domainA['id']) self.TOKEN_SCOPE_DOMAIN_B_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'domain', self.domainB['id']) self.TOKEN_SCOPE_DOMAIN_C_FROM_ADMIN = self._scope_request( self.tokens['ADMIN_ASSERTION'], 'domain', self.domainC['id']) def _inject_assertion(self, context, variant): assertion = getattr(mapping_fixtures, variant) context['environment'].update(assertion) context['query_string'] = [] keystone-2014.1/keystone/tests/test_notifications.py0000664000175400017540000005074612323716272024106 0ustar jenkinsjenkins00000000000000# Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid import mock from oslo.config import cfg from keystone.common import dependency from keystone import notifications from keystone.openstack.common.fixture import moxstubout from keystone import tests from keystone.tests import test_v3 CONF = cfg.CONF EXP_RESOURCE_TYPE = uuid.uuid4().hex class ArbitraryException(Exception): pass class NotificationsWrapperTestCase(tests.TestCase): def setUp(self): super(NotificationsWrapperTestCase, self).setUp() self.exp_resource_id = None self.exp_operation = None self.send_notification_called = False def fake_notify(operation, resource_type, resource_id, public=True): self.assertEqual(self.exp_operation, operation) self.assertEqual(EXP_RESOURCE_TYPE, resource_type) self.assertEqual(self.exp_resource_id, resource_id) self.send_notification_called = True fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs self.stubs.Set(notifications, '_send_notification', fake_notify) @notifications.created(EXP_RESOURCE_TYPE) def create_resource(self, resource_id, data): return data def test_resource_created_notification(self): self.exp_operation = 'created' self.exp_resource_id = uuid.uuid4().hex exp_resource_data = { 'id': self.exp_resource_id, 'key': uuid.uuid4().hex} self.create_resource(self.exp_resource_id, exp_resource_data) self.assertTrue(self.send_notification_called) @notifications.updated(EXP_RESOURCE_TYPE) def update_resource(self, resource_id, data): return data def test_resource_updated_notification(self): self.exp_operation = 'updated' self.exp_resource_id = uuid.uuid4().hex exp_resource_data = { 'id': self.exp_resource_id, 'key': uuid.uuid4().hex} self.update_resource(self.exp_resource_id, exp_resource_data) self.assertTrue(self.send_notification_called) @notifications.deleted(EXP_RESOURCE_TYPE) def delete_resource(self, resource_id): pass def test_resource_deleted_notification(self): self.exp_operation = 'deleted' self.exp_resource_id = uuid.uuid4().hex self.delete_resource(self.exp_resource_id) self.assertTrue(self.send_notification_called) @notifications.created(EXP_RESOURCE_TYPE) def create_exception(self, resource_id): raise ArbitraryException() def test_create_exception_without_notification(self): self.assertRaises( ArbitraryException, self.create_exception, uuid.uuid4().hex) self.assertFalse(self.send_notification_called) @notifications.created(EXP_RESOURCE_TYPE) def update_exception(self, resource_id): raise ArbitraryException() def test_update_exception_without_notification(self): self.assertRaises( ArbitraryException, self.update_exception, uuid.uuid4().hex) self.assertFalse(self.send_notification_called) @notifications.deleted(EXP_RESOURCE_TYPE) def delete_exception(self, resource_id): raise ArbitraryException() def test_delete_exception_without_notification(self): self.assertRaises( ArbitraryException, self.delete_exception, uuid.uuid4().hex) self.assertFalse(self.send_notification_called) class NotificationsTestCase(tests.TestCase): def setUp(self): super(NotificationsTestCase, self).setUp() fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs # these should use self.config_fixture.config(), but they haven't # been registered yet CONF.rpc_backend = 'fake' CONF.notification_driver = ['fake'] def test_send_notification(self): """Test the private method _send_notification to ensure event_type, payload, and context are built and passed properly. """ resource = uuid.uuid4().hex resource_type = EXP_RESOURCE_TYPE operation = 'created' # NOTE(ldbragst): Even though notifications._send_notification doesn't # contain logic that creates cases, this is suppose to test that # context is always empty and that we ensure the resource ID of the # resource in the notification is contained in the payload. It was # agreed that context should be empty in Keystone's case, which is # also noted in the /keystone/notifications.py module. This test # ensures and maintains these conditions. expected_args = [ {}, # empty context 'identity.%s.created' % resource_type, # event_type {'resource_info': resource}, # payload 'INFO', # priority is always INFO... ] with mock.patch.object(notifications._get_notifier(), '_notify') as mocked: notifications._send_notification(operation, resource_type, resource) mocked.assert_called_once_with(*expected_args) notifications._send_notification(operation, resource_type, resource) class NotificationsForEntities(test_v3.RestfulTestCase): def setUp(self): super(NotificationsForEntities, self).setUp() self._notifications = [] def fake_notify(operation, resource_type, resource_id, public=True): note = { 'resource_id': resource_id, 'operation': operation, 'resource_type': resource_type, 'send_notification_called': True, 'public': public} self._notifications.append(note) fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs self.stubs.Set(notifications, '_send_notification', fake_notify) def _assertNotifySeen(self, resource_id, operation, resource_type): self.assertIn(operation, self.exp_operations) self.assertIn(resource_id, self.exp_resource_ids) self.assertIn(resource_type, self.exp_resource_types) self.assertTrue(self.send_notification_called) def _assertLastNotify(self, resource_id, operation, resource_type): self.assertTrue(len(self._notifications) > 0) note = self._notifications[-1] self.assertEqual(note['operation'], operation) self.assertEqual(note['resource_id'], resource_id) self.assertEqual(note['resource_type'], resource_type) self.assertTrue(note['send_notification_called']) def _assertNotifyNotSent(self, resource_id, operation, resource_type, public=True): unexpected = { 'resource_id': resource_id, 'operation': operation, 'resource_type': resource_type, 'send_notification_called': True, 'public': public} for note in self._notifications: self.assertNotEqual(unexpected, note) def _assertNotifySent(self, resource_id, operation, resource_type, public): expected = { 'resource_id': resource_id, 'operation': operation, 'resource_type': resource_type, 'send_notification_called': True, 'public': public} for note in self._notifications: if expected == note: break else: self.fail("Notification not sent.") def test_create_group(self): group_ref = self.new_group_ref(domain_id=self.domain_id) self.identity_api.create_group(group_ref['id'], group_ref) self._assertLastNotify(group_ref['id'], 'created', 'group') def test_create_project(self): project_ref = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_ref['id'], project_ref) self._assertLastNotify(project_ref['id'], 'created', 'project') def test_create_role(self): role_ref = self.new_role_ref() self.assignment_api.create_role(role_ref['id'], role_ref) self._assertLastNotify(role_ref['id'], 'created', 'role') def test_create_user(self): user_ref = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(user_ref['id'], user_ref) self._assertLastNotify(user_ref['id'], 'created', 'user') def test_create_trust(self): trustor = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(trustor['id'], trustor) trustee = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(trustee['id'], trustee) role_ref = self.new_role_ref() self.assignment_api.create_role(role_ref['id'], role_ref) trust_ref = self.new_trust_ref(trustor['id'], trustee['id']) self.trust_api.create_trust(trust_ref['id'], trust_ref, [role_ref]) self._assertLastNotify(trust_ref['id'], 'created', 'OS-TRUST:trust') def test_delete_group(self): group_ref = self.new_group_ref(domain_id=self.domain_id) self.identity_api.create_group(group_ref['id'], group_ref) self.identity_api.delete_group(group_ref['id']) self._assertLastNotify(group_ref['id'], 'deleted', 'group') def test_delete_project(self): project_ref = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_ref['id'], project_ref) self.assignment_api.delete_project(project_ref['id']) self._assertLastNotify(project_ref['id'], 'deleted', 'project') def test_delete_role(self): role_ref = self.new_role_ref() self.assignment_api.create_role(role_ref['id'], role_ref) self.assignment_api.delete_role(role_ref['id']) self._assertLastNotify(role_ref['id'], 'deleted', 'role') def test_delete_user(self): user_ref = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(user_ref['id'], user_ref) self.identity_api.delete_user(user_ref['id']) self._assertLastNotify(user_ref['id'], 'deleted', 'user') def test_update_domain(self): domain_ref = self.new_domain_ref() self.assignment_api.create_domain(domain_ref['id'], domain_ref) domain_ref['description'] = uuid.uuid4().hex self.assignment_api.update_domain(domain_ref['id'], domain_ref) self._assertLastNotify(domain_ref['id'], 'updated', 'domain') def test_delete_trust(self): trustor = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(trustor['id'], trustor) trustee = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(trustee['id'], trustee) role_ref = self.new_role_ref() trust_ref = self.new_trust_ref(trustor['id'], trustee['id']) self.trust_api.create_trust(trust_ref['id'], trust_ref, [role_ref]) self.trust_api.delete_trust(trust_ref['id']) self._assertLastNotify(trust_ref['id'], 'deleted', 'OS-TRUST:trust') def test_delete_domain(self): domain_ref = self.new_domain_ref() self.assignment_api.create_domain(domain_ref['id'], domain_ref) domain_ref['enabled'] = False self.assignment_api.update_domain(domain_ref['id'], domain_ref) self.assignment_api.delete_domain(domain_ref['id']) self._assertLastNotify(domain_ref['id'], 'deleted', 'domain') def test_disable_domain(self): domain_ref = self.new_domain_ref() self.assignment_api.create_domain(domain_ref['id'], domain_ref) domain_ref['enabled'] = False self.assignment_api.update_domain(domain_ref['id'], domain_ref) self._assertNotifySent(domain_ref['id'], 'disabled', 'domain', public=False) def test_update_group(self): group_ref = self.new_group_ref(domain_id=self.domain_id) self.identity_api.create_group(group_ref['id'], group_ref) self.identity_api.update_group(group_ref['id'], group_ref) self._assertLastNotify(group_ref['id'], 'updated', 'group') def test_update_project(self): project_ref = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_ref['id'], project_ref) self.assignment_api.update_project(project_ref['id'], project_ref) self._assertNotifySent(project_ref['id'], 'updated', 'project', public=True) def test_disable_project(self): project_ref = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_ref['id'], project_ref) project_ref['enabled'] = False self.assignment_api.update_project(project_ref['id'], project_ref) self._assertNotifySent(project_ref['id'], 'disabled', 'project', public=False) def test_update_project_does_not_send_disable(self): project_ref = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_ref['id'], project_ref) project_ref['enabled'] = True self.assignment_api.update_project(project_ref['id'], project_ref) self._assertLastNotify(project_ref['id'], 'updated', 'project') self._assertNotifyNotSent(project_ref['id'], 'disabled', 'project') def test_update_role(self): role_ref = self.new_role_ref() self.assignment_api.create_role(role_ref['id'], role_ref) self.assignment_api.update_role(role_ref['id'], role_ref) self._assertLastNotify(role_ref['id'], 'updated', 'role') def test_update_user(self): user_ref = self.new_user_ref(domain_id=self.domain_id) self.identity_api.create_user(user_ref['id'], user_ref) self.identity_api.update_user(user_ref['id'], user_ref) self._assertLastNotify(user_ref['id'], 'updated', 'user') class TestEventCallbacks(test_v3.RestfulTestCase): def setUp(self): super(TestEventCallbacks, self).setUp() notifications.SUBSCRIBERS = {} self.has_been_called = False def _project_deleted_callback(self, service, resource_type, operation, payload): self.has_been_called = True def _project_created_callback(self, service, resource_type, operation, payload): self.has_been_called = True def test_notification_received(self): notifications.register_event_callback('created', 'project', self._project_created_callback) project_ref = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_ref['id'], project_ref) self.assertTrue(self.has_been_called) def test_notification_method_not_callable(self): fake_method = None notifications.SUBSCRIBERS = {} self.assertRaises(TypeError, notifications.register_event_callback, 'updated', 'project', [fake_method]) def test_notification_event_not_valid(self): self.assertRaises(ValueError, notifications.register_event_callback, uuid.uuid4().hex, 'project', self._project_deleted_callback) def test_event_registration_for_unknown_resource_type(self): # Registration for unknown resource types should succeed. If no event # is issued for that resource type, the callback wont be triggered. notifications.register_event_callback('deleted', uuid.uuid4().hex, self._project_deleted_callback) resource_type = uuid.uuid4().hex notifications.register_event_callback('deleted', resource_type, self._project_deleted_callback) self.assertIn('deleted', notifications.SUBSCRIBERS) self.assertIn(resource_type, notifications.SUBSCRIBERS['deleted']) def test_provider_event_callbacks_subscription(self): @dependency.provider('foo_api') class Foo: def __init__(self): self.event_callbacks = { 'created': { 'project': [self.foo_callback]}} def foo_callback(self, service, resource_type, operation, payload): pass notifications.SUBSCRIBERS = {} Foo() self.assertIn('created', notifications.SUBSCRIBERS) def test_invalid_event_callbacks(self): @dependency.provider('foo_api') class Foo: def __init__(self): self.event_callbacks = 'bogus' notifications.SUBSCRIBERS = {} self.assertRaises(ValueError, Foo) def test_invalid_event_callbacks_event(self): @dependency.provider('foo_api') class Foo: def __init__(self): self.event_callbacks = {'created': 'bogus'} notifications.SUBSCRIBERS = {} self.assertRaises(ValueError, Foo) class CadfNotificationsWrapperTestCase(test_v3.RestfulTestCase): LOCAL_HOST = 'localhost' ACTION = 'authenticate' def setUp(self): super(CadfNotificationsWrapperTestCase, self).setUp() self._notifications = [] def fake_notify(action, initiator, outcome): note = { 'action': action, 'initiator': initiator, # NOTE(stevemar): outcome has 2 stages, pending and success # so we are ignoring it for now. #'outcome': outcome, 'send_notification_called': True} self._notifications.append(note) # TODO(stevemar): Look into using mock instead of mox fixture = self.useFixture(moxstubout.MoxStubout()) self.stubs = fixture.stubs self.stubs.Set(notifications, '_send_audit_notification', fake_notify) def _assertLastNotify(self, action, user_id): self.assertTrue(self._notifications) note = self._notifications[-1] self.assertEqual(note['action'], action) initiator = note['initiator'] self.assertEqual(initiator.name, user_id) self.assertEqual(initiator.host.address, self.LOCAL_HOST) self.assertTrue(note['send_notification_called']) def test_v3_authenticate_user_name_and_domain_id(self): user_id = self.user_id user_name = self.user['name'] password = self.user['password'] domain_id = self.domain_id data = self.build_authentication_request(username=user_name, user_domain_id=domain_id, password=password) self.post('/auth/tokens', body=data) self._assertLastNotify(self.ACTION, user_id) def test_v3_authenticate_user_id(self): user_id = self.user_id password = self.user['password'] data = self.build_authentication_request(user_id=user_id, password=password) self.post('/auth/tokens', body=data) self._assertLastNotify(self.ACTION, user_id) def test_v3_authenticate_user_name_and_domain_name(self): user_id = self.user_id user_name = self.user['name'] password = self.user['password'] domain_name = self.domain['name'] data = self.build_authentication_request(username=user_name, user_domain_name=domain_name, password=password) self.post('/auth/tokens', body=data) self._assertLastNotify(self.ACTION, user_id) keystone-2014.1/keystone/tests/test_utils.py0000664000175400017540000001407712323716267022376 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. # Copyright 2012 Justin Santa Barbara # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import datetime import functools import os import time from keystone.common import utils from keystone import service from keystone import tests TZ = None def timezone(func): @functools.wraps(func) def wrapper(*args, **kwargs): tz_original = os.environ.get('TZ') try: if TZ: os.environ['TZ'] = TZ time.tzset() return func(*args, **kwargs) finally: if TZ: if tz_original: os.environ['TZ'] = tz_original else: if 'TZ' in os.environ: del os.environ['TZ'] time.tzset() return wrapper class UtilsTestCase(tests.TestCase): OPTIONAL = object() def test_hash(self): password = 'right' wrong = 'wrongwrong' # Two wrongs don't make a right hashed = utils.hash_password(password) self.assertTrue(utils.check_password(password, hashed)) self.assertFalse(utils.check_password(wrong, hashed)) def test_hash_long_password(self): bigboy = '0' * 9999999 hashed = utils.hash_password(bigboy) self.assertTrue(utils.check_password(bigboy, hashed)) def _create_test_user(self, password=OPTIONAL): user = {"name": "hthtest"} if password is not self.OPTIONAL: user['password'] = password return user def test_hash_user_password_without_password(self): user = self._create_test_user() hashed = utils.hash_user_password(user) self.assertEqual(user, hashed) def test_hash_user_password_with_null_password(self): user = self._create_test_user(password=None) hashed = utils.hash_user_password(user) self.assertEqual(user, hashed) def test_hash_user_password_with_empty_password(self): password = '' user = self._create_test_user(password=password) user_hashed = utils.hash_user_password(user) password_hashed = user_hashed['password'] self.assertTrue(utils.check_password(password, password_hashed)) def test_hash_ldap_user_password_without_password(self): user = self._create_test_user() hashed = utils.hash_ldap_user_password(user) self.assertEqual(user, hashed) def test_hash_ldap_user_password_with_null_password(self): user = self._create_test_user(password=None) hashed = utils.hash_ldap_user_password(user) self.assertEqual(user, hashed) def test_hash_ldap_user_password_with_empty_password(self): password = '' user = self._create_test_user(password=password) user_hashed = utils.hash_ldap_user_password(user) password_hashed = user_hashed['password'] self.assertTrue(utils.ldap_check_password(password, password_hashed)) def test_hash_edge_cases(self): hashed = utils.hash_password('secret') self.assertFalse(utils.check_password('', hashed)) self.assertFalse(utils.check_password(None, hashed)) def test_hash_unicode(self): password = u'Comment \xe7a va' wrong = 'Comment ?a va' hashed = utils.hash_password(password) self.assertTrue(utils.check_password(password, hashed)) self.assertFalse(utils.check_password(wrong, hashed)) def test_auth_str_equal(self): self.assertTrue(utils.auth_str_equal('abc123', 'abc123')) self.assertFalse(utils.auth_str_equal('a', 'aaaaa')) self.assertFalse(utils.auth_str_equal('aaaaa', 'a')) self.assertFalse(utils.auth_str_equal('ABC123', 'abc123')) def test_unixtime(self): global TZ @timezone def _test_unixtime(): epoch = utils.unixtime(dt) self.assertEqual(epoch, epoch_ans, "TZ=%s" % TZ) dt = datetime.datetime(1970, 1, 2, 3, 4, 56, 0) epoch_ans = 56 + 4 * 60 + 3 * 3600 + 86400 for d in ['+0', '-11', '-8', '-5', '+5', '+8', '+14']: TZ = 'UTC' + d _test_unixtime() class ServiceHelperTests(tests.TestCase): @service.fail_gracefully def _do_test(self): raise Exception("Test Exc") def test_fail_gracefully(self): self.assertRaises(tests.UnexpectedExit, self._do_test) class LimitingReaderTests(tests.TestCase): def test_read_default_value(self): class FakeData(object): def read(self, *args, **kwargs): self.read_args = args self.read_kwargs = kwargs return 'helloworld' data = FakeData() utils.LimitingReader(data, 100) self.assertEqual(data.read(), 'helloworld') self.assertEqual(len(data.read_args), 0) self.assertEqual(len(data.read_kwargs), 0) self.assertEqual(data.read(10), 'helloworld') self.assertEqual(len(data.read_args), 1) self.assertEqual(len(data.read_kwargs), 0) self.assertEqual(data.read_args[0], 10) keystone-2014.1/keystone/tests/rest.py0000664000175400017540000002162112323716267021145 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import io from lxml import etree import six import webtest from keystone.auth import controllers as auth_controllers from keystone.common import serializer from keystone.openstack.common import jsonutils from keystone import tests from keystone.tests import default_fixtures class RestfulTestCase(tests.TestCase): """Performs restful tests against the WSGI app over HTTP. This class launches public & admin WSGI servers for every test, which can be accessed by calling ``public_request()`` or ``admin_request()``, respectfully. ``restful_request()`` and ``request()`` methods are also exposed if you need to bypass restful conventions or access HTTP details in your test implementation. Three new asserts are provided: * ``assertResponseSuccessful``: called automatically for every request unless an ``expected_status`` is provided * ``assertResponseStatus``: called instead of ``assertResponseSuccessful``, if an ``expected_status`` is provided * ``assertValidResponseHeaders``: validates that the response headers appear as expected Requests are automatically serialized according to the defined ``content_type``. Responses are automatically deserialized as well, and available in the ``response.body`` attribute. The original body content is available in the ``response.raw`` attribute. """ # default content type to test content_type = 'json' def setUp(self, app_conf='keystone'): super(RestfulTestCase, self).setUp() # Will need to reset the plug-ins self.addCleanup(setattr, auth_controllers, 'AUTH_METHODS', {}) self.load_backends() self.load_fixtures(default_fixtures) self.public_app = webtest.TestApp( self.loadapp(app_conf, name='main')) self.addCleanup(delattr, self, 'public_app') self.admin_app = webtest.TestApp( self.loadapp(app_conf, name='admin')) self.addCleanup(delattr, self, 'admin_app') def request(self, app, path, body=None, headers=None, token=None, expected_status=None, **kwargs): if headers: headers = dict([(str(k), str(v)) for k, v in six.iteritems(headers)]) else: headers = {} if token: headers['X-Auth-Token'] = str(token) # setting body this way because of: # https://github.com/Pylons/webtest/issues/71 if body: kwargs['body_file'] = io.BytesIO(body) # sets environ['REMOTE_ADDR'] kwargs.setdefault('remote_addr', 'localhost') response = app.request(path, headers=headers, status=expected_status, **kwargs) return response def assertResponseSuccessful(self, response): """Asserts that a status code lies inside the 2xx range. :param response: :py:class:`httplib.HTTPResponse` to be verified to have a status code between 200 and 299. example:: self.assertResponseSuccessful(response, 203) """ self.assertTrue( response.status_code >= 200 and response.status_code <= 299, 'Status code %d is outside of the expected range (2xx)\n\n%s' % (response.status, response.body)) def assertResponseStatus(self, response, expected_status): """Asserts a specific status code on the response. :param response: :py:class:`httplib.HTTPResponse` :param expected_status: The specific ``status`` result expected example:: self.assertResponseStatus(response, 203) """ self.assertEqual( response.status_code, expected_status, 'Status code %s is not %s, as expected)\n\n%s' % (response.status_code, expected_status, response.body)) def assertValidResponseHeaders(self, response): """Ensures that response headers appear as expected.""" self.assertIn('X-Auth-Token', response.headers.get('Vary')) def assertValidErrorResponse(self, response, expected_status=400): """Verify that the error response is valid. Subclasses can override this function based on the expected response. """ self.assertEqual(response.status_code, expected_status) error = response.result['error'] self.assertEqual(error['code'], response.status_code) self.assertIsNotNone(error.get('title')) def _to_content_type(self, body, headers, content_type=None): """Attempt to encode JSON and XML automatically.""" content_type = content_type or self.content_type if content_type == 'json': headers['Accept'] = 'application/json' if body: headers['Content-Type'] = 'application/json' return jsonutils.dumps(body) elif content_type == 'xml': headers['Accept'] = 'application/xml' if body: headers['Content-Type'] = 'application/xml' return serializer.to_xml(body) def _from_content_type(self, response, content_type=None): """Attempt to decode JSON and XML automatically, if detected.""" content_type = content_type or self.content_type if response.body is not None and response.body.strip(): # if a body is provided, a Content-Type is also expected header = response.headers.get('Content-Type') self.assertIn(content_type, header) if content_type == 'json': response.result = jsonutils.loads(response.body) elif content_type == 'xml': response.result = etree.fromstring(response.body) def restful_request(self, method='GET', headers=None, body=None, content_type=None, **kwargs): """Serializes/deserializes json/xml as request/response body. .. WARNING:: * Existing Accept header will be overwritten. * Existing Content-Type header will be overwritten. """ # Initialize headers dictionary headers = {} if not headers else headers body = self._to_content_type(body, headers, content_type) # Perform the HTTP request/response response = self.request(method=method, headers=headers, body=body, **kwargs) self._from_content_type(response, content_type) # we can save some code & improve coverage by always doing this if method != 'HEAD' and response.status_code >= 400: self.assertValidErrorResponse(response) # Contains the decoded response.body return response def _request(self, convert=True, **kwargs): if convert: response = self.restful_request(**kwargs) else: response = self.request(**kwargs) self.assertValidResponseHeaders(response) return response def public_request(self, **kwargs): return self._request(app=self.public_app, **kwargs) def admin_request(self, **kwargs): return self._request(app=self.admin_app, **kwargs) def _get_token(self, body): """Convenience method so that we can test authenticated requests.""" r = self.public_request(method='POST', path='/v2.0/tokens', body=body) return self._get_token_id(r) def get_unscoped_token(self): """Convenience method so that we can test authenticated requests.""" return self._get_token({ 'auth': { 'passwordCredentials': { 'username': self.user_foo['name'], 'password': self.user_foo['password'], }, }, }) def get_scoped_token(self, tenant_id=None): """Convenience method so that we can test authenticated requests.""" if not tenant_id: tenant_id = self.tenant_bar['id'] return self._get_token({ 'auth': { 'passwordCredentials': { 'username': self.user_foo['name'], 'password': self.user_foo['password'], }, 'tenantId': tenant_id, }, }) def _get_token_id(self, r): """Helper method to return a token ID from a response. This needs to be overridden by child classes for on their content type. """ raise NotImplementedError() keystone-2014.1/keystone/tests/test_v3.py0000664000175400017540000012274612323716272021565 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import datetime import uuid from lxml import etree import six from testtools import matchers from keystone import auth from keystone.common import authorization from keystone.common import cache from keystone.common import serializer from keystone import config from keystone import middleware from keystone.openstack.common import timeutils from keystone.policy.backends import rules from keystone import tests from keystone.tests import rest CONF = config.CONF DEFAULT_DOMAIN_ID = 'default' TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' class RestfulTestCase(tests.SQLDriverOverrides, rest.RestfulTestCase): def config_files(self): config_files = super(RestfulTestCase, self).config_files() config_files.append(tests.dirs.tests_conf('backend_sql.conf')) return config_files def setup_database(self): tests.setup_database() def teardown_database(self): tests.teardown_database() def generate_paste_config(self): new_paste_file = None try: new_paste_file = tests.generate_paste_config(self.EXTENSION_TO_ADD) except AttributeError: # no need to report this error here, as most tests will not have # EXTENSION_TO_ADD defined. pass finally: return new_paste_file def remove_generated_paste_config(self): try: tests.remove_generated_paste_config(self.EXTENSION_TO_ADD) except AttributeError: pass def setUp(self, app_conf='keystone'): """Setup for v3 Restful Test Cases. """ new_paste_file = self.generate_paste_config() self.addCleanup(self.remove_generated_paste_config) if new_paste_file: app_conf = 'config:%s' % (new_paste_file) super(RestfulTestCase, self).setUp(app_conf=app_conf) self.empty_context = {'environment': {}} #drop the policy rules self.addCleanup(rules.reset) self.addCleanup(self.teardown_database) def load_backends(self): self.setup_database() # ensure the cache region instance is setup cache.configure_cache_region(cache.REGION) super(RestfulTestCase, self).load_backends() def load_fixtures(self, fixtures): self.load_sample_data() def load_sample_data(self): self.domain_id = uuid.uuid4().hex self.domain = self.new_domain_ref() self.domain['id'] = self.domain_id self.assignment_api.create_domain(self.domain_id, self.domain) self.project_id = uuid.uuid4().hex self.project = self.new_project_ref( domain_id=self.domain_id) self.project['id'] = self.project_id self.assignment_api.create_project(self.project_id, self.project) self.user_id = uuid.uuid4().hex self.user = self.new_user_ref(domain_id=self.domain_id) self.user['id'] = self.user_id self.identity_api.create_user(self.user_id, self.user) self.default_domain_project_id = uuid.uuid4().hex self.default_domain_project = self.new_project_ref( domain_id=DEFAULT_DOMAIN_ID) self.default_domain_project['id'] = self.default_domain_project_id self.assignment_api.create_project(self.default_domain_project_id, self.default_domain_project) self.default_domain_user_id = uuid.uuid4().hex self.default_domain_user = self.new_user_ref( domain_id=DEFAULT_DOMAIN_ID) self.default_domain_user['id'] = self.default_domain_user_id self.identity_api.create_user(self.default_domain_user_id, self.default_domain_user) # create & grant policy.json's default role for admin_required self.role_id = uuid.uuid4().hex self.role = self.new_role_ref() self.role['id'] = self.role_id self.role['name'] = 'admin' self.assignment_api.create_role(self.role_id, self.role) self.assignment_api.add_role_to_user_and_project( self.user_id, self.project_id, self.role_id) self.assignment_api.add_role_to_user_and_project( self.default_domain_user_id, self.default_domain_project_id, self.role_id) self.assignment_api.add_role_to_user_and_project( self.default_domain_user_id, self.project_id, self.role_id) self.region_id = uuid.uuid4().hex self.region = self.new_region_ref() self.region['id'] = self.region_id self.catalog_api.create_region( self.region.copy()) self.service_id = uuid.uuid4().hex self.service = self.new_service_ref() self.service['id'] = self.service_id self.catalog_api.create_service( self.service_id, self.service.copy()) self.endpoint_id = uuid.uuid4().hex self.endpoint = self.new_endpoint_ref(service_id=self.service_id) self.endpoint['id'] = self.endpoint_id self.catalog_api.create_endpoint( self.endpoint_id, self.endpoint.copy()) # The server adds 'enabled' and defaults to True. self.endpoint['enabled'] = True def new_ref(self): """Populates a ref with attributes common to all API entities.""" return { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, 'enabled': True} def new_region_ref(self): ref = self.new_ref() # Region doesn't have name or enabled. del ref['name'] del ref['enabled'] ref['parent_region_id'] = None return ref def new_service_ref(self): ref = self.new_ref() ref['type'] = uuid.uuid4().hex return ref def new_endpoint_ref(self, service_id, **kwargs): ref = self.new_ref() del ref['enabled'] # enabled is optional ref['interface'] = uuid.uuid4().hex[:8] ref['service_id'] = service_id ref['url'] = uuid.uuid4().hex ref['region'] = uuid.uuid4().hex ref.update(kwargs) return ref def new_domain_ref(self): ref = self.new_ref() return ref def new_project_ref(self, domain_id): ref = self.new_ref() ref['domain_id'] = domain_id return ref def new_user_ref(self, domain_id, project_id=None): ref = self.new_ref() ref['domain_id'] = domain_id ref['email'] = uuid.uuid4().hex ref['password'] = uuid.uuid4().hex if project_id: ref['default_project_id'] = project_id return ref def new_group_ref(self, domain_id): ref = self.new_ref() ref['domain_id'] = domain_id return ref def new_credential_ref(self, user_id, project_id=None): ref = self.new_ref() ref['user_id'] = user_id ref['blob'] = uuid.uuid4().hex ref['type'] = uuid.uuid4().hex if project_id: ref['project_id'] = project_id return ref def new_role_ref(self): ref = self.new_ref() return ref def new_policy_ref(self): ref = self.new_ref() ref['blob'] = uuid.uuid4().hex ref['type'] = uuid.uuid4().hex return ref def new_trust_ref(self, trustor_user_id, trustee_user_id, project_id=None, impersonation=None, expires=None, role_ids=None, role_names=None, remaining_uses=None): ref = self.new_ref() ref['trustor_user_id'] = trustor_user_id ref['trustee_user_id'] = trustee_user_id ref['impersonation'] = impersonation or False ref['project_id'] = project_id ref['remaining_uses'] = remaining_uses if isinstance(expires, six.string_types): ref['expires_at'] = expires elif isinstance(expires, dict): ref['expires_at'] = timeutils.strtime( timeutils.utcnow() + datetime.timedelta(**expires), fmt=TIME_FORMAT) elif expires is None: pass else: raise NotImplementedError('Unexpected value for "expires"') role_ids = role_ids or [] role_names = role_names or [] if role_ids or role_names: ref['roles'] = [] for role_id in role_ids: ref['roles'].append({'id': role_id}) for role_name in role_names: ref['roles'].append({'name': role_name}) return ref def create_new_default_project_for_user(self, user_id, domain_id, enable_project=True): ref = self.new_project_ref(domain_id=domain_id) ref['enabled'] = enable_project r = self.post('/projects', body={'project': ref}) project = self.assertValidProjectResponse(r, ref) # set the user's preferred project body = {'user': {'default_project_id': project['id']}} r = self.patch('/users/%(user_id)s' % { 'user_id': user_id}, body=body) self.assertValidUserResponse(r) return project def admin_request(self, *args, **kwargs): """Translates XML responses to dicts. This implies that we only have to write assertions for JSON. """ r = super(RestfulTestCase, self).admin_request(*args, **kwargs) if r.headers.get('Content-Type') == 'application/xml': r.result = serializer.from_xml(etree.tostring(r.result)) return r def get_scoped_token(self): """Convenience method so that we can test authenticated requests.""" r = self.admin_request( method='POST', path='/v3/auth/tokens', body={ 'auth': { 'identity': { 'methods': ['password'], 'password': { 'user': { 'name': self.user['name'], 'password': self.user['password'], 'domain': { 'id': self.user['domain_id'] } } } }, 'scope': { 'project': { 'id': self.project['id'], } } } }) return r.headers.get('X-Subject-Token') def get_requested_token(self, auth): """Request the specific token we want.""" r = self.admin_request( method='POST', path='/v3/auth/tokens', body=auth) return r.headers.get('X-Subject-Token') def v3_request(self, path, **kwargs): # Check if the caller has passed in auth details for # use in requesting the token auth_arg = kwargs.pop('auth', None) if auth_arg: token = self.get_requested_token(auth_arg) else: token = kwargs.pop('token', None) if not token: token = self.get_scoped_token() path = '/v3' + path return self.admin_request(path=path, token=token, **kwargs) def get(self, path, **kwargs): r = self.v3_request(method='GET', path=path, **kwargs) if 'expected_status' not in kwargs: self.assertResponseStatus(r, 200) return r def head(self, path, **kwargs): r = self.v3_request(method='HEAD', path=path, **kwargs) if 'expected_status' not in kwargs: self.assertResponseStatus(r, 204) return r def post(self, path, **kwargs): r = self.v3_request(method='POST', path=path, **kwargs) if 'expected_status' not in kwargs: self.assertResponseStatus(r, 201) return r def put(self, path, **kwargs): r = self.v3_request(method='PUT', path=path, **kwargs) if 'expected_status' not in kwargs: self.assertResponseStatus(r, 204) return r def patch(self, path, **kwargs): r = self.v3_request(method='PATCH', path=path, **kwargs) if 'expected_status' not in kwargs: self.assertResponseStatus(r, 200) return r def delete(self, path, **kwargs): r = self.v3_request(method='DELETE', path=path, **kwargs) if 'expected_status' not in kwargs: self.assertResponseStatus(r, 204) return r def assertValidErrorResponse(self, r): if r.headers.get('Content-Type') == 'application/xml': resp = serializer.from_xml(etree.tostring(r.result)) else: resp = r.result self.assertIsNotNone(resp.get('error')) self.assertIsNotNone(resp['error'].get('code')) self.assertIsNotNone(resp['error'].get('title')) self.assertIsNotNone(resp['error'].get('message')) self.assertEqual(int(resp['error']['code']), r.status_code) def assertValidListLinks(self, links): self.assertIsNotNone(links) self.assertIsNotNone(links.get('self')) self.assertThat(links['self'], matchers.StartsWith('http://localhost')) self.assertIn('next', links) if links['next'] is not None: self.assertThat(links['next'], matchers.StartsWith('http://localhost')) self.assertIn('previous', links) if links['previous'] is not None: self.assertThat(links['previous'], matchers.StartsWith('http://localhost')) def assertValidListResponse(self, resp, key, entity_validator, ref=None, expected_length=None, keys_to_check=None): """Make assertions common to all API list responses. If a reference is provided, it's ID will be searched for in the response, and asserted to be equal. """ entities = resp.result.get(key) self.assertIsNotNone(entities) if expected_length is not None: self.assertEqual(len(entities), expected_length) elif ref is not None: # we're at least expecting the ref self.assertNotEmpty(entities) # collections should have relational links self.assertValidListLinks(resp.result.get('links')) for entity in entities: self.assertIsNotNone(entity) self.assertValidEntity(entity, keys_to_check=keys_to_check) entity_validator(entity) if ref: entity = [x for x in entities if x['id'] == ref['id']][0] self.assertValidEntity(entity, ref=ref, keys_to_check=keys_to_check) entity_validator(entity, ref) return entities def assertValidResponse(self, resp, key, entity_validator, *args, **kwargs): """Make assertions common to all API responses.""" entity = resp.result.get(key) self.assertIsNotNone(entity) keys = kwargs.pop('keys_to_check', None) self.assertValidEntity(entity, keys_to_check=keys, *args, **kwargs) entity_validator(entity, *args, **kwargs) return entity def assertValidEntity(self, entity, ref=None, keys_to_check=None): """Make assertions common to all API entities. If a reference is provided, the entity will also be compared against the reference. """ if keys_to_check is not None: keys = keys_to_check else: keys = ['name', 'description', 'enabled'] for k in ['id'] + keys: msg = '%s unexpectedly None in %s' % (k, entity) self.assertIsNotNone(entity.get(k), msg) self.assertIsNotNone(entity.get('links')) self.assertIsNotNone(entity['links'].get('self')) self.assertThat(entity['links']['self'], matchers.StartsWith('http://localhost')) self.assertIn(entity['id'], entity['links']['self']) if ref: for k in keys: msg = '%s not equal: %s != %s' % (k, ref[k], entity[k]) self.assertEqual(ref[k], entity[k]) return entity # auth validation def assertValidISO8601ExtendedFormatDatetime(self, dt): try: return timeutils.parse_strtime(dt, fmt=TIME_FORMAT) except Exception: msg = '%s is not a valid ISO 8601 extended format date time.' % dt raise AssertionError(msg) self.assertIsInstance(dt, datetime.datetime) def assertValidTokenResponse(self, r, user=None): self.assertTrue(r.headers.get('X-Subject-Token')) token = r.result['token'] self.assertIsNotNone(token.get('expires_at')) expires_at = self.assertValidISO8601ExtendedFormatDatetime( token['expires_at']) self.assertIsNotNone(token.get('issued_at')) issued_at = self.assertValidISO8601ExtendedFormatDatetime( token['issued_at']) self.assertTrue(issued_at < expires_at) self.assertIn('user', token) self.assertIn('id', token['user']) self.assertIn('name', token['user']) self.assertIn('domain', token['user']) self.assertIn('id', token['user']['domain']) if user is not None: self.assertEqual(user['id'], token['user']['id']) self.assertEqual(user['name'], token['user']['name']) self.assertEqual(user['domain_id'], token['user']['domain']['id']) return token def assertValidUnscopedTokenResponse(self, r, *args, **kwargs): token = self.assertValidTokenResponse(r, *args, **kwargs) self.assertNotIn('roles', token) self.assertNotIn('catalog', token) self.assertNotIn('project', token) self.assertNotIn('domain', token) return token def assertValidScopedTokenResponse(self, r, *args, **kwargs): require_catalog = kwargs.pop('require_catalog', True) endpoint_filter = kwargs.pop('endpoint_filter', False) ep_filter_assoc = kwargs.pop('ep_filter_assoc', 0) token = self.assertValidTokenResponse(r, *args, **kwargs) if require_catalog: self.assertIn('catalog', token) if isinstance(token['catalog'], list): # only test JSON for service in token['catalog']: for endpoint in service['endpoints']: self.assertNotIn('enabled', endpoint) self.assertNotIn('legacy_endpoint_id', endpoint) self.assertNotIn('service_id', endpoint) # sub test for the OS-EP-FILTER extension enabled if endpoint_filter: # verify the catalog hs no more than the endpoints # associated in the catalog using the ep filter assoc self.assertTrue(len(token['catalog']) < ep_filter_assoc + 1) else: self.assertNotIn('catalog', token) self.assertIn('roles', token) self.assertTrue(token['roles']) for role in token['roles']: self.assertIn('id', role) self.assertIn('name', role) return token def assertValidProjectScopedTokenResponse(self, r, *args, **kwargs): token = self.assertValidScopedTokenResponse(r, *args, **kwargs) self.assertIn('project', token) self.assertIn('id', token['project']) self.assertIn('name', token['project']) self.assertIn('domain', token['project']) self.assertIn('id', token['project']['domain']) self.assertIn('name', token['project']['domain']) self.assertEqual(self.role_id, token['roles'][0]['id']) return token def assertValidProjectTrustScopedTokenResponse(self, r, *args, **kwargs): token = self.assertValidProjectScopedTokenResponse(r, *args, **kwargs) trust = token.get('OS-TRUST:trust') self.assertIsNotNone(trust) self.assertIsNotNone(trust.get('id')) self.assertIsInstance(trust.get('impersonation'), bool) self.assertIsNotNone(trust.get('trustor_user')) self.assertIsNotNone(trust.get('trustee_user')) self.assertIsNotNone(trust['trustor_user'].get('id')) self.assertIsNotNone(trust['trustee_user'].get('id')) def assertValidDomainScopedTokenResponse(self, r, *args, **kwargs): token = self.assertValidScopedTokenResponse(r, *args, **kwargs) self.assertIn('domain', token) self.assertIn('id', token['domain']) self.assertIn('name', token['domain']) return token def assertEqualTokens(self, a, b): """Assert that two tokens are equal. Compare two tokens except for their ids. This also truncates the time in the comparison. """ def normalize(token): del token['token']['expires_at'] del token['token']['issued_at'] return token a_expires_at = self.assertValidISO8601ExtendedFormatDatetime( a['token']['expires_at']) b_expires_at = self.assertValidISO8601ExtendedFormatDatetime( b['token']['expires_at']) self.assertCloseEnoughForGovernmentWork(a_expires_at, b_expires_at) a_issued_at = self.assertValidISO8601ExtendedFormatDatetime( a['token']['issued_at']) b_issued_at = self.assertValidISO8601ExtendedFormatDatetime( b['token']['issued_at']) self.assertCloseEnoughForGovernmentWork(a_issued_at, b_issued_at) return self.assertDictEqual(normalize(a), normalize(b)) # region validation def assertValidRegionListResponse(self, resp, *args, **kwargs): #NOTE(jaypipes): I have to pass in a blank keys_to_check parameter # below otherwise the base assertValidEntity method # tries to find a "name" and an "enabled" key in the # returned ref dicts. The issue is, I don't understand # how the service and endpoint entity assertions below # actually work (they don't raise assertions), since # AFAICT, the service and endpoint tables don't have # a "name" column either... :( return self.assertValidListResponse( resp, 'regions', self.assertValidRegion, keys_to_check=[], *args, **kwargs) def assertValidRegionResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'region', self.assertValidRegion, keys_to_check=[], *args, **kwargs) def assertValidRegion(self, entity, ref=None): self.assertIsNotNone(entity.get('description')) if ref: self.assertEqual(ref['description'], entity['description']) return entity # service validation def assertValidServiceListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'services', self.assertValidService, *args, **kwargs) def assertValidServiceResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'service', self.assertValidService, *args, **kwargs) def assertValidService(self, entity, ref=None): self.assertIsNotNone(entity.get('type')) self.assertIsInstance(entity.get('enabled'), bool) if ref: self.assertEqual(ref['type'], entity['type']) return entity # endpoint validation def assertValidEndpointListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'endpoints', self.assertValidEndpoint, *args, **kwargs) def assertValidEndpointResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'endpoint', self.assertValidEndpoint, *args, **kwargs) def assertValidEndpoint(self, entity, ref=None): self.assertIsNotNone(entity.get('interface')) self.assertIsNotNone(entity.get('service_id')) self.assertIsInstance(entity['enabled'], bool) # this is intended to be an unexposed implementation detail self.assertNotIn('legacy_endpoint_id', entity) if ref: self.assertEqual(ref['interface'], entity['interface']) self.assertEqual(ref['service_id'], entity['service_id']) return entity # domain validation def assertValidDomainListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'domains', self.assertValidDomain, *args, **kwargs) def assertValidDomainResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'domain', self.assertValidDomain, *args, **kwargs) def assertValidDomain(self, entity, ref=None): if ref: pass return entity # project validation def assertValidProjectListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'projects', self.assertValidProject, *args, **kwargs) def assertValidProjectResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'project', self.assertValidProject, *args, **kwargs) def assertValidProject(self, entity, ref=None): self.assertIsNotNone(entity.get('domain_id')) if ref: self.assertEqual(ref['domain_id'], entity['domain_id']) return entity # user validation def assertValidUserListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'users', self.assertValidUser, *args, **kwargs) def assertValidUserResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'user', self.assertValidUser, *args, **kwargs) def assertValidUser(self, entity, ref=None): self.assertIsNotNone(entity.get('domain_id')) self.assertIsNotNone(entity.get('email')) self.assertIsNone(entity.get('password')) self.assertNotIn('tenantId', entity) if ref: self.assertEqual(ref['domain_id'], entity['domain_id']) self.assertEqual(ref['email'], entity['email']) if 'default_project_id' in ref: self.assertIsNotNone(ref['default_project_id']) self.assertEqual(ref['default_project_id'], entity['default_project_id']) return entity # group validation def assertValidGroupListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'groups', self.assertValidGroup, *args, **kwargs) def assertValidGroupResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'group', self.assertValidGroup, *args, **kwargs) def assertValidGroup(self, entity, ref=None): self.assertIsNotNone(entity.get('name')) if ref: self.assertEqual(ref['name'], entity['name']) return entity # credential validation def assertValidCredentialListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'credentials', self.assertValidCredential, *args, **kwargs) def assertValidCredentialResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'credential', self.assertValidCredential, *args, **kwargs) def assertValidCredential(self, entity, ref=None): self.assertIsNotNone(entity.get('user_id')) self.assertIsNotNone(entity.get('blob')) self.assertIsNotNone(entity.get('type')) if ref: self.assertEqual(ref['user_id'], entity['user_id']) self.assertEqual(ref['blob'], entity['blob']) self.assertEqual(ref['type'], entity['type']) self.assertEqual(ref.get('project_id'), entity.get('project_id')) return entity # role validation def assertValidRoleListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'roles', self.assertValidRole, keys_to_check=['name'], *args, **kwargs) def assertValidRoleResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'role', self.assertValidRole, keys_to_check=['name'], *args, **kwargs) def assertValidRole(self, entity, ref=None): self.assertIsNotNone(entity.get('name')) if ref: self.assertEqual(ref['name'], entity['name']) return entity def assertValidRoleAssignmentListResponse(self, resp, ref=None, expected_length=None): entities = resp.result.get('role_assignments') if expected_length is not None: self.assertEqual(len(entities), expected_length) elif ref is not None: # we're at least expecting the ref self.assertNotEmpty(entities) # collections should have relational links self.assertValidListLinks(resp.result.get('links')) for entity in entities: self.assertIsNotNone(entity) self.assertValidRoleAssignment(entity) if ref: self.assertValidRoleAssignment(entity, ref) return entities def assertValidRoleAssignment(self, entity, ref=None, url=None): self.assertIsNotNone(entity.get('role')) self.assertIsNotNone(entity.get('scope')) # Only one of user or group should be present self.assertIsNotNone(entity.get('user') or entity.get('group')) self.assertIsNone(entity.get('user') and entity.get('group')) # Only one of domain or project should be present self.assertIsNotNone(entity['scope'].get('project') or entity['scope'].get('domain')) self.assertIsNone(entity['scope'].get('project') and entity['scope'].get('domain')) if entity['scope'].get('project'): self.assertIsNotNone(entity['scope']['project'].get('id')) else: self.assertIsNotNone(entity['scope']['domain'].get('id')) self.assertIsNotNone(entity.get('links')) self.assertIsNotNone(entity['links'].get('assignment')) if ref: if ref.get('user'): self.assertEqual(ref['user']['id'], entity['user']['id']) if ref.get('group'): self.assertEqual(ref['group']['id'], entity['group']['id']) if ref.get('role'): self.assertEqual(ref['role']['id'], entity['role']['id']) if ref['scope'].get('project'): self.assertEqual(ref['scope']['project']['id'], entity['scope']['project']['id']) if ref['scope'].get('domain'): self.assertEqual(ref['scope']['domain']['id'], entity['scope']['domain']['id']) if url: self.assertIn(url, entity['links']['assignment']) def assertRoleAssignmentInListResponse( self, resp, ref, link_url=None, expected=1): found_count = 0 for entity in resp.result.get('role_assignments'): try: self.assertValidRoleAssignment( entity, ref=ref, url=link_url) except Exception: # It doesn't match, so let's go onto the next one pass else: found_count += 1 self.assertEqual(found_count, expected) def assertRoleAssignmentNotInListResponse( self, resp, ref, link_url=None): self.assertRoleAssignmentInListResponse( resp, ref=ref, link_url=link_url, expected=0) # policy validation def assertValidPolicyListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'policies', self.assertValidPolicy, *args, **kwargs) def assertValidPolicyResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'policy', self.assertValidPolicy, *args, **kwargs) def assertValidPolicy(self, entity, ref=None): self.assertIsNotNone(entity.get('blob')) self.assertIsNotNone(entity.get('type')) if ref: self.assertEqual(ref['blob'], entity['blob']) self.assertEqual(ref['type'], entity['type']) return entity # trust validation def assertValidTrustListResponse(self, resp, *args, **kwargs): return self.assertValidListResponse( resp, 'trusts', self.assertValidTrustSummary, *args, **kwargs) def assertValidTrustResponse(self, resp, *args, **kwargs): return self.assertValidResponse( resp, 'trust', self.assertValidTrust, *args, **kwargs) def assertValidTrustSummary(self, entity, ref=None): return self.assertValidTrust(entity, ref, summary=True) def assertValidTrust(self, entity, ref=None, summary=False): self.assertIsNotNone(entity.get('trustor_user_id')) self.assertIsNotNone(entity.get('trustee_user_id')) self.assertIn('expires_at', entity) if entity['expires_at'] is not None: self.assertValidISO8601ExtendedFormatDatetime(entity['expires_at']) if summary: # Trust list contains no roles, but getting a specific # trust by ID provides the detailed response containing roles self.assertNotIn('roles', entity) self.assertIn('project_id', entity) else: for role in entity['roles']: self.assertIsNotNone(role) self.assertValidEntity(role) self.assertValidRole(role) self.assertValidListLinks(entity.get('roles_links')) # always disallow role xor project_id (neither or both is allowed) has_roles = bool(entity.get('roles')) has_project = bool(entity.get('project_id')) self.assertFalse(has_roles ^ has_project) if ref: self.assertEqual(ref['trustor_user_id'], entity['trustor_user_id']) self.assertEqual(ref['trustee_user_id'], entity['trustee_user_id']) self.assertEqual(ref['project_id'], entity['project_id']) if entity.get('expires_at') or ref.get('expires_at'): entity_exp = self.assertValidISO8601ExtendedFormatDatetime( entity['expires_at']) ref_exp = self.assertValidISO8601ExtendedFormatDatetime( ref['expires_at']) self.assertCloseEnoughForGovernmentWork(entity_exp, ref_exp) else: self.assertEqual(ref.get('expires_at'), entity.get('expires_at')) return entity def build_auth_scope(self, project_id=None, project_name=None, project_domain_id=None, project_domain_name=None, domain_id=None, domain_name=None, trust_id=None): scope_data = {} if project_id or project_name: scope_data['project'] = {} if project_id: scope_data['project']['id'] = project_id else: scope_data['project']['name'] = project_name if project_domain_id or project_domain_name: project_domain_json = {} if project_domain_id: project_domain_json['id'] = project_domain_id else: project_domain_json['name'] = project_domain_name scope_data['project']['domain'] = project_domain_json if domain_id or domain_name: scope_data['domain'] = {} if domain_id: scope_data['domain']['id'] = domain_id else: scope_data['domain']['name'] = domain_name if trust_id: scope_data['OS-TRUST:trust'] = {} scope_data['OS-TRUST:trust']['id'] = trust_id return scope_data def build_password_auth(self, user_id=None, username=None, user_domain_id=None, user_domain_name=None, password=None): password_data = {'user': {}} if user_id: password_data['user']['id'] = user_id else: password_data['user']['name'] = username if user_domain_id or user_domain_name: password_data['user']['domain'] = {} if user_domain_id: password_data['user']['domain']['id'] = user_domain_id else: password_data['user']['domain']['name'] = user_domain_name password_data['user']['password'] = password return password_data def build_token_auth(self, token): return {'id': token} def build_authentication_request(self, token=None, user_id=None, username=None, user_domain_id=None, user_domain_name=None, password=None, **kwargs): """Build auth dictionary. It will create an auth dictionary based on all the arguments that it receives. """ auth_data = {} auth_data['identity'] = {'methods': []} if token: auth_data['identity']['methods'].append('token') auth_data['identity']['token'] = self.build_token_auth(token) if user_id or username: auth_data['identity']['methods'].append('password') auth_data['identity']['password'] = self.build_password_auth( user_id, username, user_domain_id, user_domain_name, password) if kwargs: auth_data['scope'] = self.build_auth_scope(**kwargs) return {'auth': auth_data} def build_external_auth_request(self, remote_user, remote_domain=None, auth_data=None): context = {'environment': {'REMOTE_USER': remote_user}} if remote_domain: context['environment']['REMOTE_DOMAIN'] = remote_domain if not auth_data: auth_data = self.build_authentication_request()['auth'] no_context = None auth_info = auth.controllers.AuthInfo.create(no_context, auth_data) auth_context = {'extras': {}, 'method_names': []} return context, auth_info, auth_context class VersionTestCase(RestfulTestCase): def test_get_version(self): pass #NOTE(gyee): test AuthContextMiddleware here instead of test_middleware.py # because we need the token class AuthContextMiddlewareTestCase(RestfulTestCase): def _mock_request_object(self, token_id): class fake_req: headers = {middleware.AUTH_TOKEN_HEADER: token_id} environ = {} return fake_req() def test_auth_context_build_by_middleware(self): # test to make sure AuthContextMiddleware successful build the auth # context from the incoming auth token admin_token = self.get_scoped_token() req = self._mock_request_object(admin_token) application = None middleware.AuthContextMiddleware(application).process_request(req) self.assertEqual( req.environ.get(authorization.AUTH_CONTEXT_ENV)['user_id'], self.user['id']) def test_auth_context_override(self): overridden_context = 'OVERRIDDEN_CONTEXT' # this token should not be used token = uuid.uuid4().hex req = self._mock_request_object(token) req.environ[authorization.AUTH_CONTEXT_ENV] = overridden_context application = None middleware.AuthContextMiddleware(application).process_request(req) # make sure overridden context take precedence self.assertEqual(req.environ.get(authorization.AUTH_CONTEXT_ENV), overridden_context) def test_admin_token_auth_context(self): # test to make sure AuthContextMiddleware does not attempt to build # auth context if the incoming auth token is the special admin token req = self._mock_request_object(CONF.admin_token) application = None middleware.AuthContextMiddleware(application).process_request(req) self.assertDictEqual(req.environ.get(authorization.AUTH_CONTEXT_ENV), {}) keystone-2014.1/keystone/tests/test_backend_kvs.py0000664000175400017540000002312112323716272023472 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import datetime import uuid import six from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import default_fixtures from keystone.tests import test_backend class KvsIdentity(tests.TestCase, test_backend.IdentityTests): def setUp(self): super(KvsIdentity, self).setUp() self.load_backends() self.load_fixtures(default_fixtures) def config_overrides(self): super(KvsIdentity, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.kvs.Identity') def test_list_projects_for_user_with_grants(self): self.skipTest('kvs backend is now deprecated') def test_create_duplicate_group_name_in_different_domains(self): self.skipTest('Blocked by bug 1119770') def test_create_duplicate_user_name_in_different_domains(self): self.skipTest('Blocked by bug 1119770') def test_create_duplicate_project_name_in_different_domains(self): self.skipTest('Blocked by bug 1119770') def test_move_user_between_domains(self): self.skipTest('Blocked by bug 1119770') def test_move_user_between_domains_with_clashing_names_fails(self): self.skipTest('Blocked by bug 1119770') def test_move_group_between_domains(self): self.skipTest('Blocked by bug 1119770') def test_move_group_between_domains_with_clashing_names_fails(self): self.skipTest('Blocked by bug 1119770') def test_move_project_between_domains(self): self.skipTest('Blocked by bug 1119770') def test_move_project_between_domains_with_clashing_names_fails(self): self.skipTest('Blocked by bug 1119770') class KvsToken(tests.TestCase, test_backend.TokenTests): def setUp(self): super(KvsToken, self).setUp() self.load_backends() def config_overrides(self): super(KvsToken, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.kvs.Identity') def test_flush_expired_token(self): self.assertRaises(exception.NotImplemented, self.token_api.flush_expired_tokens) def _update_user_token_index_direct(self, user_key, token_id, new_data): token_list = self.token_api.driver._get_user_token_list_with_expiry( user_key) # Update the user-index so that the expires time is _actually_ expired # since we do not do an explicit get on the token, we only reference # the data in the user index (to save extra round-trips to the kvs # backend). for i, data in enumerate(token_list): if data[0] == token_id: token_list[i] = new_data break self.token_api.driver._store.set(user_key, token_list) def test_cleanup_user_index_on_create(self): user_id = six.text_type(uuid.uuid4().hex) valid_token_id, data = self.create_token_sample_data(user_id=user_id) expired_token_id, expired_data = self.create_token_sample_data( user_id=user_id) expire_delta = datetime.timedelta(seconds=86400) # NOTE(morganfainberg): Directly access the data cache since we need to # get expired tokens as well as valid tokens. token_api.list_tokens() # will not return any expired tokens in the list. user_key = self.token_api.driver._prefix_user_id(user_id) user_token_list = self.token_api.driver._store.get(user_key) valid_token_ref = self.token_api.get_token(valid_token_id) expired_token_ref = self.token_api.get_token(expired_token_id) expected_user_token_list = [ (valid_token_id, timeutils.isotime(valid_token_ref['expires'], subsecond=True)), (expired_token_id, timeutils.isotime(expired_token_ref['expires'], subsecond=True))] self.assertEqual(expected_user_token_list, user_token_list) new_expired_data = (expired_token_id, timeutils.isotime( (timeutils.utcnow() - expire_delta), subsecond=True)) self._update_user_token_index_direct(user_key, expired_token_id, new_expired_data) valid_token_id_2, valid_data_2 = self.create_token_sample_data( user_id=user_id) valid_token_ref_2 = self.token_api.get_token(valid_token_id_2) expected_user_token_list = [ (valid_token_id, timeutils.isotime(valid_token_ref['expires'], subsecond=True)), (valid_token_id_2, timeutils.isotime(valid_token_ref_2['expires'], subsecond=True))] user_token_list = self.token_api.driver._store.get(user_key) self.assertEqual(expected_user_token_list, user_token_list) # Test that revoked tokens are removed from the list on create. self.token_api.delete_token(valid_token_id_2) new_token_id, data = self.create_token_sample_data(user_id=user_id) new_token_ref = self.token_api.get_token(new_token_id) expected_user_token_list = [ (valid_token_id, timeutils.isotime(valid_token_ref['expires'], subsecond=True)), (new_token_id, timeutils.isotime(new_token_ref['expires'], subsecond=True))] user_token_list = self.token_api.driver._store.get(user_key) self.assertEqual(expected_user_token_list, user_token_list) class KvsTrust(tests.TestCase, test_backend.TrustTests): def setUp(self): super(KvsTrust, self).setUp() self.load_backends() self.load_fixtures(default_fixtures) def config_overrides(self): super(KvsTrust, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.kvs.Identity') self.config_fixture.config( group='trust', driver='keystone.trust.backends.kvs.Trust') self.config_fixture.config( group='catalog', driver='keystone.catalog.backends.kvs.Catalog') class KvsCatalog(tests.TestCase, test_backend.CatalogTests): def setUp(self): super(KvsCatalog, self).setUp() self.load_backends() self._load_fake_catalog() def config_overrides(self): super(KvsCatalog, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.kvs.Identity') self.config_fixture.config( group='trust', driver='keystone.trust.backends.kvs.Trust') self.config_fixture.config( group='catalog', driver='keystone.catalog.backends.kvs.Catalog') def _load_fake_catalog(self): self.catalog_foobar = self.catalog_api.driver._create_catalog( 'foo', 'bar', {'RegionFoo': {'service_bar': {'foo': 'bar'}}}) def test_get_catalog_404(self): # FIXME(dolph): this test should be moved up to test_backend # FIXME(dolph): exceptions should be UserNotFound and ProjectNotFound self.assertRaises(exception.NotFound, self.catalog_api.get_catalog, uuid.uuid4().hex, 'bar') self.assertRaises(exception.NotFound, self.catalog_api.get_catalog, 'foo', uuid.uuid4().hex) def test_get_catalog(self): catalog_ref = self.catalog_api.get_catalog('foo', 'bar') self.assertDictEqual(catalog_ref, self.catalog_foobar) def test_get_catalog_endpoint_disabled(self): # This test doesn't apply to KVS because with the KVS backend the # application creates the catalog (including the endpoints) for each # user and project. Whether endpoints are enabled or disabled isn't # a consideration. f = super(KvsCatalog, self).test_get_catalog_endpoint_disabled self.assertRaises(exception.NotFound, f) def test_get_v3_catalog_endpoint_disabled(self): f = super(KvsCatalog, self).test_get_v3_catalog_endpoint_disabled self.assertRaises(exception.NotImplemented, f) class KvsTokenCacheInvalidation(tests.TestCase, test_backend.TokenCacheInvalidation): def setUp(self): super(KvsTokenCacheInvalidation, self).setUp() self.load_backends() self._create_test_data() def config_overrides(self): super(KvsTokenCacheInvalidation, self).config_overrides() self.config_fixture.config( group='identity', driver='keystone.identity.backends.kvs.Identity') self.config_fixture.config( group='token', driver='keystone.token.backends.kvs.Token') keystone-2014.1/keystone/tests/test_token_bind.py0000664000175400017540000001601212323716267023341 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import wsgi from keystone import exception from keystone import tests KERBEROS_BIND = 'USER@REALM' # the only thing the function checks for is the presence of bind TOKEN_BIND_KERB = {'bind': {'kerberos': KERBEROS_BIND}} TOKEN_BIND_UNKNOWN = {'bind': {'FOO': 'BAR'}} TOKEN_BIND_NONE = {} ANY = 'any' ALL_TOKENS = [TOKEN_BIND_KERB, TOKEN_BIND_UNKNOWN, TOKEN_BIND_NONE] class BindTest(tests.TestCase): """Test binding tokens to a Principal. Even though everything in this file references kerberos the same concepts will apply to all future binding mechanisms. """ def assert_kerberos_bind(self, tokens, bind_level, use_kerberos=True, success=True): if not isinstance(tokens, dict): for token in tokens: self.assert_kerberos_bind(token, bind_level, use_kerberos=use_kerberos, success=success) elif use_kerberos == ANY: for val in (True, False): self.assert_kerberos_bind(tokens, bind_level, use_kerberos=val, success=success) else: context = {'environment': {}} self.config_fixture.config(group='token', enforce_token_bind=bind_level) if use_kerberos: context['environment']['REMOTE_USER'] = KERBEROS_BIND context['environment']['AUTH_TYPE'] = 'Negotiate' if not success: self.assertRaises(exception.Unauthorized, wsgi.validate_token_bind, context, tokens) else: wsgi.validate_token_bind(context, tokens) # DISABLED def test_bind_disabled_with_kerb_user(self): self.assert_kerberos_bind(ALL_TOKENS, bind_level='disabled', use_kerberos=ANY, success=True) # PERMISSIVE def test_bind_permissive_with_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='permissive', use_kerberos=True, success=True) def test_bind_permissive_with_regular_token(self): self.assert_kerberos_bind(TOKEN_BIND_NONE, bind_level='permissive', use_kerberos=ANY, success=True) def test_bind_permissive_without_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='permissive', use_kerberos=False, success=False) def test_bind_permissive_with_unknown_bind(self): self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN, bind_level='permissive', use_kerberos=ANY, success=True) # STRICT def test_bind_strict_with_regular_token(self): self.assert_kerberos_bind(TOKEN_BIND_NONE, bind_level='strict', use_kerberos=ANY, success=True) def test_bind_strict_with_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='strict', use_kerberos=True, success=True) def test_bind_strict_without_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='strict', use_kerberos=False, success=False) def test_bind_strict_with_unknown_bind(self): self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN, bind_level='strict', use_kerberos=ANY, success=False) # REQUIRED def test_bind_required_with_regular_token(self): self.assert_kerberos_bind(TOKEN_BIND_NONE, bind_level='required', use_kerberos=ANY, success=False) def test_bind_required_with_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='required', use_kerberos=True, success=True) def test_bind_required_without_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='required', use_kerberos=False, success=False) def test_bind_required_with_unknown_bind(self): self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN, bind_level='required', use_kerberos=ANY, success=False) # NAMED def test_bind_named_with_regular_token(self): self.assert_kerberos_bind(TOKEN_BIND_NONE, bind_level='kerberos', use_kerberos=ANY, success=False) def test_bind_named_with_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='kerberos', use_kerberos=True, success=True) def test_bind_named_without_kerb_user(self): self.assert_kerberos_bind(TOKEN_BIND_KERB, bind_level='kerberos', use_kerberos=False, success=False) def test_bind_named_with_unknown_bind(self): self.assert_kerberos_bind(TOKEN_BIND_UNKNOWN, bind_level='kerberos', use_kerberos=ANY, success=False) def test_bind_named_with_unknown_scheme(self): self.assert_kerberos_bind(ALL_TOKENS, bind_level='unknown', use_kerberos=ANY, success=False) keystone-2014.1/keystone/tests/test_auth.py0000664000175400017540000012720612323716272022172 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import copy import datetime import uuid import mock from keystone import assignment from keystone import auth from keystone.common import authorization from keystone.common import environment from keystone import config from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import default_fixtures from keystone import token from keystone import trust CONF = config.CONF TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id HOST_URL = 'http://keystone:5001' def _build_user_auth(token=None, user_id=None, username=None, password=None, tenant_id=None, tenant_name=None, trust_id=None): """Build auth dictionary. It will create an auth dictionary based on all the arguments that it receives. """ auth_json = {} if token is not None: auth_json['token'] = token if username or password: auth_json['passwordCredentials'] = {} if username is not None: auth_json['passwordCredentials']['username'] = username if user_id is not None: auth_json['passwordCredentials']['userId'] = user_id if password is not None: auth_json['passwordCredentials']['password'] = password if tenant_name is not None: auth_json['tenantName'] = tenant_name if tenant_id is not None: auth_json['tenantId'] = tenant_id if trust_id is not None: auth_json['trust_id'] = trust_id return auth_json class AuthTest(tests.TestCase): def setUp(self): super(AuthTest, self).setUp() self.load_backends() self.load_fixtures(default_fixtures) # need to register the token provider first because auth controller # depends on it token.provider.Manager() self.context_with_remote_user = {'environment': {'REMOTE_USER': 'FOO', 'AUTH_TYPE': 'Negotiate'}} self.empty_context = {'environment': {}} self.controller = token.controllers.Auth() #This call sets up, among other things, the call to popen #that will be used to run the CMS command. These tests were #passing only due to the global nature of the call. If the #tests in this file are run alone, API calls return unauthorized. environment.use_eventlet(monkeypatch_thread=False) def assertEqualTokens(self, a, b): """Assert that two tokens are equal. Compare two tokens except for their ids. This also truncates the time in the comparison. """ def normalize(token): token['access']['token']['id'] = 'dummy' del token['access']['token']['expires'] del token['access']['token']['issued_at'] return token self.assertCloseEnoughForGovernmentWork( timeutils.parse_isotime(a['access']['token']['expires']), timeutils.parse_isotime(b['access']['token']['expires'])) self.assertCloseEnoughForGovernmentWork( timeutils.parse_isotime(a['access']['token']['issued_at']), timeutils.parse_isotime(b['access']['token']['issued_at'])) return self.assertDictEqual(normalize(a), normalize(b)) class AuthBadRequests(AuthTest): def setUp(self): super(AuthBadRequests, self).setUp() def test_no_external_auth(self): """Verify that _authenticate_external() raises exception if N/A.""" self.assertRaises( token.controllers.ExternalAuthNotApplicable, self.controller._authenticate_external, {}, {}) def test_no_token_in_auth(self): """Verify that _authenticate_token() raises exception if no token.""" self.assertRaises( exception.ValidationError, self.controller._authenticate_token, None, {}) def test_no_credentials_in_auth(self): """Verify that _authenticate_local() raises exception if no creds.""" self.assertRaises( exception.ValidationError, self.controller._authenticate_local, None, {}) def test_authenticate_blank_request_body(self): """Verify sending empty json dict raises the right exception.""" self.assertRaises(exception.ValidationError, self.controller.authenticate, {}, {}) def test_authenticate_blank_auth(self): """Verify sending blank 'auth' raises the right exception.""" body_dict = _build_user_auth() self.assertRaises(exception.ValidationError, self.controller.authenticate, {}, body_dict) def test_authenticate_invalid_auth_content(self): """Verify sending invalid 'auth' raises the right exception.""" self.assertRaises(exception.ValidationError, self.controller.authenticate, {}, {'auth': 'abcd'}) def test_authenticate_user_id_too_large(self): """Verify sending large 'userId' raises the right exception.""" body_dict = _build_user_auth(user_id='0' * 65, username='FOO', password='foo2') self.assertRaises(exception.ValidationSizeError, self.controller.authenticate, {}, body_dict) def test_authenticate_username_too_large(self): """Verify sending large 'username' raises the right exception.""" body_dict = _build_user_auth(username='0' * 65, password='foo2') self.assertRaises(exception.ValidationSizeError, self.controller.authenticate, {}, body_dict) def test_authenticate_tenant_id_too_large(self): """Verify sending large 'tenantId' raises the right exception.""" body_dict = _build_user_auth(username='FOO', password='foo2', tenant_id='0' * 65) self.assertRaises(exception.ValidationSizeError, self.controller.authenticate, {}, body_dict) def test_authenticate_tenant_name_too_large(self): """Verify sending large 'tenantName' raises the right exception.""" body_dict = _build_user_auth(username='FOO', password='foo2', tenant_name='0' * 65) self.assertRaises(exception.ValidationSizeError, self.controller.authenticate, {}, body_dict) def test_authenticate_token_too_large(self): """Verify sending large 'token' raises the right exception.""" body_dict = _build_user_auth(token={'id': '0' * 8193}) self.assertRaises(exception.ValidationSizeError, self.controller.authenticate, {}, body_dict) def test_authenticate_password_too_large(self): """Verify sending large 'password' raises the right exception.""" length = CONF.identity.max_password_length + 1 body_dict = _build_user_auth(username='FOO', password='0' * length) self.assertRaises(exception.ValidationSizeError, self.controller.authenticate, {}, body_dict) class AuthWithToken(AuthTest): def setUp(self): super(AuthWithToken, self).setUp() def test_unscoped_token(self): """Verify getting an unscoped token with password creds.""" body_dict = _build_user_auth(username='FOO', password='foo2') unscoped_token = self.controller.authenticate({}, body_dict) self.assertNotIn('tenant', unscoped_token['access']['token']) def test_auth_invalid_token(self): """Verify exception is raised if invalid token.""" body_dict = _build_user_auth(token={"id": uuid.uuid4().hex}) self.assertRaises( exception.Unauthorized, self.controller.authenticate, {}, body_dict) def test_auth_bad_formatted_token(self): """Verify exception is raised if invalid token.""" body_dict = _build_user_auth(token={}) self.assertRaises( exception.ValidationError, self.controller.authenticate, {}, body_dict) def test_auth_unscoped_token_no_project(self): """Verify getting an unscoped token with an unscoped token.""" body_dict = _build_user_auth( username='FOO', password='foo2') unscoped_token = self.controller.authenticate({}, body_dict) body_dict = _build_user_auth( token=unscoped_token["access"]["token"]) unscoped_token_2 = self.controller.authenticate({}, body_dict) self.assertEqualTokens(unscoped_token, unscoped_token_2) def test_auth_unscoped_token_project(self): """Verify getting a token in a tenant with an unscoped token.""" # Add a role in so we can check we get this back self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_member['id']) # Get an unscoped tenant body_dict = _build_user_auth( username='FOO', password='foo2') unscoped_token = self.controller.authenticate({}, body_dict) # Get a token on BAR tenant using the unscoped tenant body_dict = _build_user_auth( token=unscoped_token["access"]["token"], tenant_name="BAR") scoped_token = self.controller.authenticate({}, body_dict) tenant = scoped_token["access"]["token"]["tenant"] roles = scoped_token["access"]["metadata"]["roles"] self.assertEqual(self.tenant_bar['id'], tenant["id"]) self.assertEqual(self.role_member['id'], roles[0]) def test_auth_token_project_group_role(self): """Verify getting a token in a tenant with group roles.""" # Add a v2 style role in so we can check we get this back self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_member['id']) # Now create a group role for this user as well domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) new_group = {'id': uuid.uuid4().hex, 'domain_id': domain1['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) self.identity_api.add_user_to_group(self.user_foo['id'], new_group['id']) self.assignment_api.create_grant( group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id=self.role_admin['id']) # Get a scoped token for the tenant body_dict = _build_user_auth( username='FOO', password='foo2', tenant_name="BAR") scoped_token = self.controller.authenticate({}, body_dict) tenant = scoped_token["access"]["token"]["tenant"] roles = scoped_token["access"]["metadata"]["roles"] self.assertEqual(self.tenant_bar['id'], tenant["id"]) self.assertIn(self.role_member['id'], roles) self.assertIn(self.role_admin['id'], roles) def test_auth_token_cross_domain_group_and_project(self): """Verify getting a token in cross domain group/project roles.""" # create domain, project and group and grant roles to user domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) role_foo_domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role_foo_domain1['id'], role_foo_domain1) role_group_domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role_group_domain1['id'], role_group_domain1) self.assignment_api.add_user_to_project(project1['id'], self.user_foo['id']) new_group = {'id': uuid.uuid4().hex, 'domain_id': domain1['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) self.identity_api.add_user_to_group(self.user_foo['id'], new_group['id']) self.assignment_api.create_grant( user_id=self.user_foo['id'], project_id=project1['id'], role_id=self.role_member['id']) self.assignment_api.create_grant( group_id=new_group['id'], project_id=project1['id'], role_id=self.role_admin['id']) self.assignment_api.create_grant( user_id=self.user_foo['id'], domain_id=domain1['id'], role_id=role_foo_domain1['id']) self.assignment_api.create_grant( group_id=new_group['id'], domain_id=domain1['id'], role_id=role_group_domain1['id']) # Get a scoped token for the tenant body_dict = _build_user_auth( username=self.user_foo['name'], password=self.user_foo['password'], tenant_name=project1['name']) scoped_token = self.controller.authenticate({}, body_dict) tenant = scoped_token["access"]["token"]["tenant"] roles = scoped_token["access"]["metadata"]["roles"] self.assertEqual(project1['id'], tenant["id"]) self.assertIn(self.role_member['id'], roles) self.assertIn(self.role_admin['id'], roles) self.assertNotIn(role_foo_domain1['id'], roles) self.assertNotIn(role_group_domain1['id'], roles) def test_belongs_to_no_tenant(self): r = self.controller.authenticate( {}, auth={ 'passwordCredentials': { 'username': self.user_foo['name'], 'password': self.user_foo['password'] } }) unscoped_token_id = r['access']['token']['id'] self.assertRaises( exception.Unauthorized, self.controller.validate_token, dict(is_admin=True, query_string={'belongsTo': 'BAR'}), token_id=unscoped_token_id) def test_belongs_to(self): body_dict = _build_user_auth( username='FOO', password='foo2', tenant_name="BAR") scoped_token = self.controller.authenticate({}, body_dict) scoped_token_id = scoped_token['access']['token']['id'] self.assertRaises( exception.Unauthorized, self.controller.validate_token, dict(is_admin=True, query_string={'belongsTo': 'me'}), token_id=scoped_token_id) self.assertRaises( exception.Unauthorized, self.controller.validate_token, dict(is_admin=True, query_string={'belongsTo': 'BAR'}), token_id=scoped_token_id) def test_token_auth_with_binding(self): self.config_fixture.config(group='token', bind=['kerberos']) body_dict = _build_user_auth() unscoped_token = self.controller.authenticate( self.context_with_remote_user, body_dict) # the token should have bind information in it bind = unscoped_token['access']['token']['bind'] self.assertEqual('FOO', bind['kerberos']) body_dict = _build_user_auth( token=unscoped_token['access']['token'], tenant_name='BAR') # using unscoped token without remote user context fails self.assertRaises( exception.Unauthorized, self.controller.authenticate, self.empty_context, body_dict) # using token with remote user context succeeds scoped_token = self.controller.authenticate( self.context_with_remote_user, body_dict) # the bind information should be carried over from the original token bind = scoped_token['access']['token']['bind'] self.assertEqual('FOO', bind['kerberos']) def test_deleting_role_revokes_token(self): role_controller = assignment.controllers.Role() project1 = {'id': 'Project1', 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(project1['id'], project1) role_one = {'id': 'role_one', 'name': uuid.uuid4().hex} self.assignment_api.create_role(role_one['id'], role_one) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], project1['id'], role_one['id']) no_context = {} # Get a scoped token for the tenant body_dict = _build_user_auth( username=self.user_foo['name'], password=self.user_foo['password'], tenant_name=project1['name']) token = self.controller.authenticate(no_context, body_dict) # Ensure it is valid token_id = token['access']['token']['id'] self.controller.validate_token( dict(is_admin=True, query_string={}), token_id=token_id) # Delete the role, which should invalidate the token role_controller.delete_role( dict(is_admin=True, query_string={}), role_one['id']) # Check the token is now invalid self.assertRaises( exception.TokenNotFound, self.controller.validate_token, dict(is_admin=True, query_string={}), token_id=token_id) class AuthWithPasswordCredentials(AuthTest): def setUp(self): super(AuthWithPasswordCredentials, self).setUp() def test_auth_invalid_user(self): """Verify exception is raised if invalid user.""" body_dict = _build_user_auth( username=uuid.uuid4().hex, password=uuid.uuid4().hex) self.assertRaises( exception.Unauthorized, self.controller.authenticate, {}, body_dict) def test_auth_valid_user_invalid_password(self): """Verify exception is raised if invalid password.""" body_dict = _build_user_auth( username="FOO", password=uuid.uuid4().hex) self.assertRaises( exception.Unauthorized, self.controller.authenticate, {}, body_dict) def test_auth_empty_password(self): """Verify exception is raised if empty password.""" body_dict = _build_user_auth( username="FOO", password="") self.assertRaises( exception.Unauthorized, self.controller.authenticate, {}, body_dict) def test_auth_no_password(self): """Verify exception is raised if empty password.""" body_dict = _build_user_auth(username="FOO") self.assertRaises( exception.ValidationError, self.controller.authenticate, {}, body_dict) def test_authenticate_blank_password_credentials(self): """Sending empty dict as passwordCredentials raises a 400 error.""" body_dict = {'passwordCredentials': {}, 'tenantName': 'demo'} self.assertRaises(exception.ValidationError, self.controller.authenticate, {}, body_dict) def test_authenticate_no_username(self): """Verify skipping username raises the right exception.""" body_dict = _build_user_auth(password="pass", tenant_name="demo") self.assertRaises(exception.ValidationError, self.controller.authenticate, {}, body_dict) def test_bind_without_remote_user(self): self.config_fixture.config(group='token', bind=['kerberos']) body_dict = _build_user_auth(username='FOO', password='foo2', tenant_name='BAR') token = self.controller.authenticate({}, body_dict) self.assertNotIn('bind', token['access']['token']) def test_change_default_domain_id(self): # If the default_domain_id config option is not the default then the # user in auth data is from the new default domain. # 1) Create a new domain. new_domain_id = uuid.uuid4().hex new_domain = { 'description': uuid.uuid4().hex, 'enabled': True, 'id': new_domain_id, 'name': uuid.uuid4().hex, } self.assignment_api.create_domain(new_domain_id, new_domain) # 2) Create user "foo" in new domain with different password than # default-domain foo. new_user_id = uuid.uuid4().hex new_user_password = uuid.uuid4().hex new_user = { 'id': new_user_id, 'name': self.user_foo['name'], 'domain_id': new_domain_id, 'password': new_user_password, 'email': 'foo@bar2.com', } self.identity_api.create_user(new_user_id, new_user) # 3) Update the default_domain_id config option to the new domain self.config_fixture.config(group='identity', default_domain_id=new_domain_id) # 4) Authenticate as "foo" using the password in the new domain. body_dict = _build_user_auth( username=self.user_foo['name'], password=new_user_password) # The test is successful if this doesn't raise, so no need to assert. self.controller.authenticate({}, body_dict) class AuthWithRemoteUser(AuthTest): def setUp(self): super(AuthWithRemoteUser, self).setUp() def test_unscoped_remote_authn(self): """Verify getting an unscoped token with external authn.""" body_dict = _build_user_auth( username='FOO', password='foo2') local_token = self.controller.authenticate( {}, body_dict) body_dict = _build_user_auth() remote_token = self.controller.authenticate( self.context_with_remote_user, body_dict) self.assertEqualTokens(local_token, remote_token) def test_unscoped_remote_authn_jsonless(self): """Verify that external auth with invalid request fails.""" self.assertRaises( exception.ValidationError, self.controller.authenticate, {'REMOTE_USER': 'FOO'}, None) def test_scoped_remote_authn(self): """Verify getting a token with external authn.""" body_dict = _build_user_auth( username='FOO', password='foo2', tenant_name='BAR') local_token = self.controller.authenticate( {}, body_dict) body_dict = _build_user_auth( tenant_name='BAR') remote_token = self.controller.authenticate( self.context_with_remote_user, body_dict) self.assertEqualTokens(local_token, remote_token) def test_scoped_nometa_remote_authn(self): """Verify getting a token with external authn and no metadata.""" body_dict = _build_user_auth( username='TWO', password='two2', tenant_name='BAZ') local_token = self.controller.authenticate( {}, body_dict) body_dict = _build_user_auth(tenant_name='BAZ') remote_token = self.controller.authenticate( {'environment': {'REMOTE_USER': 'TWO'}}, body_dict) self.assertEqualTokens(local_token, remote_token) def test_scoped_remote_authn_invalid_user(self): """Verify that external auth with invalid user fails.""" body_dict = _build_user_auth(tenant_name="BAR") self.assertRaises( exception.Unauthorized, self.controller.authenticate, {'environment': {'REMOTE_USER': uuid.uuid4().hex}}, body_dict) def test_bind_with_kerberos(self): self.config_fixture.config(group='token', bind=['kerberos']) body_dict = _build_user_auth(tenant_name="BAR") token = self.controller.authenticate(self.context_with_remote_user, body_dict) self.assertEqual('FOO', token['access']['token']['bind']['kerberos']) def test_bind_without_config_opt(self): self.config_fixture.config(group='token', bind=['x509']) body_dict = _build_user_auth(tenant_name='BAR') token = self.controller.authenticate(self.context_with_remote_user, body_dict) self.assertNotIn('bind', token['access']['token']) class AuthWithTrust(AuthTest): def setUp(self): super(AuthWithTrust, self).setUp() trust.Manager() self.trust_controller = trust.controllers.TrustV3() self.auth_v3_controller = auth.controllers.Auth() self.trustor = self.user_foo self.trustee = self.user_two self.assigned_roles = [self.role_member['id'], self.role_browser['id']] for assigned_role in self.assigned_roles: self.assignment_api.add_role_to_user_and_project( self.trustor['id'], self.tenant_bar['id'], assigned_role) self.sample_data = {'trustor_user_id': self.trustor['id'], 'trustee_user_id': self.trustee['id'], 'project_id': self.tenant_bar['id'], 'impersonation': True, 'roles': [{'id': self.role_browser['id']}, {'name': self.role_member['name']}]} expires_at = timeutils.strtime(timeutils.utcnow() + datetime.timedelta(minutes=10), fmt=TIME_FORMAT) self.create_trust(expires_at=expires_at) def config_overrides(self): super(AuthWithTrust, self).config_overrides() self.config_fixture.config(group='trust', enabled=True) def _create_auth_context(self, token_id): token_ref = self.token_api.get_token(token_id) auth_context = authorization.token_to_auth_context( token_ref['token_data']) return {'environment': {authorization.AUTH_CONTEXT_ENV: auth_context}, 'token_id': token_id, 'host_url': HOST_URL} def create_trust(self, expires_at=None, impersonation=True): username = self.trustor['name'] password = 'foo2' body_dict = _build_user_auth(username=username, password=password) self.unscoped_token = self.controller.authenticate({}, body_dict) context = self._create_auth_context( self.unscoped_token['access']['token']['id']) trust_data = copy.deepcopy(self.sample_data) trust_data['expires_at'] = expires_at trust_data['impersonation'] = impersonation self.new_trust = self.trust_controller.create_trust( context, trust=trust_data)['trust'] def build_v2_token_request(self, username, password): body_dict = _build_user_auth(username=username, password=password) self.unscoped_token = self.controller.authenticate({}, body_dict) unscoped_token_id = self.unscoped_token['access']['token']['id'] request_body = _build_user_auth(token={'id': unscoped_token_id}, trust_id=self.new_trust['id'], tenant_id=self.tenant_bar['id']) return request_body def test_create_trust_bad_data_fails(self): context = self._create_auth_context( self.unscoped_token['access']['token']['id']) bad_sample_data = {'trustor_user_id': self.trustor['id'], 'project_id': self.tenant_bar['id'], 'roles': [{'id': self.role_browser['id']}]} self.assertRaises(exception.ValidationError, self.trust_controller.create_trust, context, trust=bad_sample_data) def test_create_trust_no_roles(self): context = {'token_id': self.unscoped_token['access']['token']['id']} self.sample_data['roles'] = [] self.assertRaises(exception.Forbidden, self.trust_controller.create_trust, context, trust=self.sample_data) def test_create_trust(self): self.assertEqual(self.trustor['id'], self.new_trust['trustor_user_id']) self.assertEqual(self.trustee['id'], self.new_trust['trustee_user_id']) role_ids = [self.role_browser['id'], self.role_member['id']] self.assertTrue(timeutils.parse_strtime(self.new_trust['expires_at'], fmt=TIME_FORMAT)) self.assertIn('%s/v3/OS-TRUST/' % HOST_URL, self.new_trust['links']['self']) self.assertIn('%s/v3/OS-TRUST/' % HOST_URL, self.new_trust['roles_links']['self']) for role in self.new_trust['roles']: self.assertIn(role['id'], role_ids) def test_create_trust_expires_bad(self): self.assertRaises(exception.ValidationTimeStampError, self.create_trust, expires_at="bad") self.assertRaises(exception.ValidationTimeStampError, self.create_trust, expires_at="") self.assertRaises(exception.ValidationTimeStampError, self.create_trust, expires_at="Z") def test_get_trust(self): context = {'token_id': self.unscoped_token['access']['token']['id'], 'host_url': HOST_URL} trust = self.trust_controller.get_trust(context, self.new_trust['id'])['trust'] self.assertEqual(self.trustor['id'], trust['trustor_user_id']) self.assertEqual(self.trustee['id'], trust['trustee_user_id']) role_ids = [self.role_browser['id'], self.role_member['id']] for role in self.new_trust['roles']: self.assertIn(role['id'], role_ids) def test_create_trust_no_impersonation(self): self.create_trust(expires_at=None, impersonation=False) self.assertEqual(self.trustor['id'], self.new_trust['trustor_user_id']) self.assertEqual(self.trustee['id'], self.new_trust['trustee_user_id']) self.assertIs(self.new_trust['impersonation'], False) auth_response = self.fetch_v2_token_from_trust() token_user = auth_response['access']['user'] self.assertEqual(token_user['id'], self.new_trust['trustee_user_id']) # TODO(ayoung): Endpoints def test_create_trust_impersonation(self): self.create_trust(expires_at=None) self.assertEqual(self.trustor['id'], self.new_trust['trustor_user_id']) self.assertEqual(self.trustee['id'], self.new_trust['trustee_user_id']) self.assertIs(self.new_trust['impersonation'], True) auth_response = self.fetch_v2_token_from_trust() token_user = auth_response['access']['user'] self.assertEqual(token_user['id'], self.new_trust['trustor_user_id']) def test_token_from_trust_wrong_user_fails(self): request_body = self.build_v2_token_request('FOO', 'foo2') self.assertRaises( exception.Forbidden, self.controller.authenticate, {}, request_body) def fetch_v2_token_from_trust(self): request_body = self.build_v2_token_request('TWO', 'two2') auth_response = self.controller.authenticate({}, request_body) return auth_response def fetch_v3_token_from_trust(self): v3_password_data = { 'identity': { "methods": ["password"], "password": { "user": { "id": self.trustee["id"], "password": self.trustee["password"]}} }, 'scope': { 'project': { 'id': self.tenant_baz['id']}}} auth_response = (self.auth_v3_controller.authenticate_for_token ({'environment': {}, 'query_string': {}}, v3_password_data)) token = auth_response.headers['X-Subject-Token'] v3_req_with_trust = { "identity": { "methods": ["token"], "token": {"id": token}}, "scope": { "OS-TRUST:trust": {"id": self.new_trust['id']}}} token_auth_response = (self.auth_v3_controller.authenticate_for_token ({'environment': {}, 'query_string': {}}, v3_req_with_trust)) return token_auth_response def test_create_v3_token_from_trust(self): auth_response = self.fetch_v3_token_from_trust() trust_token_user = auth_response.json['token']['user'] self.assertEqual(self.trustor['id'], trust_token_user['id']) trust_token_trust = auth_response.json['token']['OS-TRUST:trust'] self.assertEqual(trust_token_trust['id'], self.new_trust['id']) self.assertEqual(self.trustor['id'], trust_token_trust['trustor_user']['id']) self.assertEqual(self.trustee['id'], trust_token_trust['trustee_user']['id']) trust_token_roles = auth_response.json['token']['roles'] self.assertEqual(2, len(trust_token_roles)) def test_v3_trust_token_get_token_fails(self): auth_response = self.fetch_v3_token_from_trust() trust_token = auth_response.headers['X-Subject-Token'] v3_token_data = {'identity': { 'methods': ['token'], 'token': {'id': trust_token} }} self.assertRaises( exception.Forbidden, self.auth_v3_controller.authenticate_for_token, {'environment': {}, 'query_string': {}}, v3_token_data) def test_token_from_trust(self): auth_response = self.fetch_v2_token_from_trust() self.assertIsNotNone(auth_response) self.assertEqual(2, len(auth_response['access']['metadata']['roles']), "user_foo has three roles, but the token should" " only get the two roles specified in the trust.") def assert_token_count_for_trust(self, expected_value): tokens = self.trust_controller.token_api._list_tokens( self.trustee['id'], trust_id=self.new_trust['id']) token_count = len(tokens) self.assertEqual(expected_value, token_count) def test_delete_tokens_for_user_invalidates_tokens_from_trust(self): self.assert_token_count_for_trust(0) self.fetch_v2_token_from_trust() self.assert_token_count_for_trust(1) self.token_api.delete_tokens_for_user(self.trustee['id']) self.assert_token_count_for_trust(0) def test_token_from_trust_cant_get_another_token(self): auth_response = self.fetch_v2_token_from_trust() trust_token_id = auth_response['access']['token']['id'] request_body = _build_user_auth(token={'id': trust_token_id}, tenant_id=self.tenant_bar['id']) self.assertRaises( exception.Forbidden, self.controller.authenticate, {}, request_body) def test_delete_trust_revokes_token(self): context = self._create_auth_context( self.unscoped_token['access']['token']['id']) self.fetch_v2_token_from_trust() trust_id = self.new_trust['id'] tokens = self.token_api._list_tokens(self.trustor['id'], trust_id=trust_id) self.assertEqual(1, len(tokens)) self.trust_controller.delete_trust(context, trust_id=trust_id) tokens = self.token_api._list_tokens(self.trustor['id'], trust_id=trust_id) self.assertEqual(0, len(tokens)) def test_token_from_trust_with_no_role_fails(self): for assigned_role in self.assigned_roles: self.assignment_api.remove_role_from_user_and_project( self.trustor['id'], self.tenant_bar['id'], assigned_role) request_body = self.build_v2_token_request('TWO', 'two2') self.assertRaises( exception.Forbidden, self.controller.authenticate, {}, request_body) def test_expired_trust_get_token_fails(self): expiry = "1999-02-18T10:10:00Z" self.create_trust(expiry) request_body = self.build_v2_token_request('TWO', 'two2') self.assertRaises( exception.Forbidden, self.controller.authenticate, {}, request_body) def test_token_from_trust_with_wrong_role_fails(self): self.assignment_api.add_role_to_user_and_project( self.trustor['id'], self.tenant_bar['id'], self.role_other['id']) for assigned_role in self.assigned_roles: self.assignment_api.remove_role_from_user_and_project( self.trustor['id'], self.tenant_bar['id'], assigned_role) request_body = self.build_v2_token_request('TWO', 'two2') self.assertRaises( exception.Forbidden, self.controller.authenticate, {}, request_body) class TokenExpirationTest(AuthTest): @mock.patch.object(timeutils, 'utcnow') def _maintain_token_expiration(self, mock_utcnow): """Token expiration should be maintained after re-auth & validation.""" now = datetime.datetime.utcnow() mock_utcnow.return_value = now r = self.controller.authenticate( {}, auth={ 'passwordCredentials': { 'username': self.user_foo['name'], 'password': self.user_foo['password'] } }) unscoped_token_id = r['access']['token']['id'] original_expiration = r['access']['token']['expires'] mock_utcnow.return_value = now + datetime.timedelta(seconds=1) r = self.controller.validate_token( dict(is_admin=True, query_string={}), token_id=unscoped_token_id) self.assertEqual(original_expiration, r['access']['token']['expires']) mock_utcnow.return_value = now + datetime.timedelta(seconds=2) r = self.controller.authenticate( {}, auth={ 'token': { 'id': unscoped_token_id, }, 'tenantId': self.tenant_bar['id'], }) scoped_token_id = r['access']['token']['id'] self.assertEqual(original_expiration, r['access']['token']['expires']) mock_utcnow.return_value = now + datetime.timedelta(seconds=3) r = self.controller.validate_token( dict(is_admin=True, query_string={}), token_id=scoped_token_id) self.assertEqual(original_expiration, r['access']['token']['expires']) def test_maintain_uuid_token_expiration(self): self.config_fixture.config(group='signing', token_format='UUID') self._maintain_token_expiration() class AuthCatalog(tests.SQLDriverOverrides, AuthTest): """Tests for the catalog provided in the auth response.""" def config_files(self): config_files = super(AuthCatalog, self).config_files() # We need to use a backend that supports disabled endpoints, like the # SQL backend. config_files.append(tests.dirs.tests_conf('backend_sql.conf')) return config_files def _create_endpoints(self): def create_endpoint(service_id, region, **kwargs): id_ = uuid.uuid4().hex ref = { 'id': id_, 'interface': 'public', 'region': region, 'service_id': service_id, 'url': 'http://localhost/%s' % uuid.uuid4().hex, } ref.update(kwargs) self.catalog_api.create_endpoint(id_, ref) return ref # Create a service for use with the endpoints. def create_service(**kwargs): id_ = uuid.uuid4().hex ref = { 'id': id_, 'name': uuid.uuid4().hex, 'type': uuid.uuid4().hex, } ref.update(kwargs) self.catalog_api.create_service(id_, ref) return ref enabled_service_ref = create_service(enabled=True) disabled_service_ref = create_service(enabled=False) region = uuid.uuid4().hex # Create endpoints enabled_endpoint_ref = create_endpoint( enabled_service_ref['id'], region) create_endpoint( enabled_service_ref['id'], region, enabled=False, interface='internal') create_endpoint( disabled_service_ref['id'], region) return enabled_endpoint_ref def test_auth_catalog_disabled_endpoint(self): """On authenticate, get a catalog that excludes disabled endpoints.""" endpoint_ref = self._create_endpoints() # Authenticate body_dict = _build_user_auth( username='FOO', password='foo2', tenant_name="BAR") token = self.controller.authenticate({}, body_dict) # Check the catalog self.assertEqual(1, len(token['access']['serviceCatalog'])) endpoint = token['access']['serviceCatalog'][0]['endpoints'][0] self.assertEqual( 1, len(token['access']['serviceCatalog'][0]['endpoints'])) exp_endpoint = { 'id': endpoint_ref['id'], 'publicURL': endpoint_ref['url'], 'region': endpoint_ref['region'], } self.assertEqual(exp_endpoint, endpoint) def test_validate_catalog_disabled_endpoint(self): """On validate, get back a catalog that excludes disabled endpoints.""" endpoint_ref = self._create_endpoints() # Authenticate body_dict = _build_user_auth( username='FOO', password='foo2', tenant_name="BAR") token = self.controller.authenticate({}, body_dict) # Validate token_id = token['access']['token']['id'] validate_ref = self.controller.validate_token( dict(is_admin=True, query_string={}), token_id=token_id) # Check the catalog self.assertEqual(1, len(token['access']['serviceCatalog'])) endpoint = validate_ref['access']['serviceCatalog'][0]['endpoints'][0] self.assertEqual( 1, len(token['access']['serviceCatalog'][0]['endpoints'])) exp_endpoint = { 'id': endpoint_ref['id'], 'publicURL': endpoint_ref['url'], 'region': endpoint_ref['region'], } self.assertEqual(exp_endpoint, endpoint) class NonDefaultAuthTest(tests.TestCase): def test_add_non_default_auth_method(self): self.config_fixture.config(group='auth', methods=['password', 'token', 'custom']) config.setup_authentication() self.assertTrue(hasattr(CONF.auth, 'custom')) keystone-2014.1/keystone/tests/test_v3_os_revoke.py0000664000175400017540000001125512323716267023635 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import datetime import uuid from keystone.common import dependency from keystone.contrib.revoke import model from keystone.openstack.common import timeutils from keystone.tests import test_v3 from keystone import token def _future_time_string(): expire_delta = datetime.timedelta(seconds=1000) future_time = timeutils.utcnow() + expire_delta return timeutils.isotime(future_time) @dependency.requires('revoke_api') class OSRevokeTests(test_v3.RestfulTestCase): EXTENSION_NAME = 'revoke' EXTENSION_TO_ADD = 'revoke_extension' def test_get_empty_list(self): resp = self.get('/OS-REVOKE/events') self.assertEqual([], resp.json_body['events']) def _blank_event(self): return {} # The two values will be the same with the exception of # 'issued_before' which is set when the event is recorded. def assertReportedEventMatchesRecorded(self, event, sample, before_time): after_time = timeutils.utcnow() event_issued_before = timeutils.normalize_time( timeutils.parse_isotime(event['issued_before'])) self.assertTrue( before_time <= event_issued_before, 'invalid event issued_before time; %s is not later than %s.' % ( timeutils.isotime(event_issued_before, subsecond=True), timeutils.isotime(before_time, subsecond=True))) self.assertTrue( event_issued_before <= after_time, 'invalid event issued_before time; %s is not earlier than %s.' % ( timeutils.isotime(event_issued_before, subsecond=True), timeutils.isotime(after_time, subsecond=True))) del (event['issued_before']) self.assertEqual(sample, event) def test_revoked_token_in_list(self): user_id = uuid.uuid4().hex expires_at = token.default_expire_time() sample = self._blank_event() sample['user_id'] = unicode(user_id) sample['expires_at'] = unicode(timeutils.isotime(expires_at, subsecond=True)) before_time = timeutils.utcnow() self.revoke_api.revoke_by_expiration(user_id, expires_at) resp = self.get('/OS-REVOKE/events') events = resp.json_body['events'] self.assertEqual(len(events), 1) self.assertReportedEventMatchesRecorded(events[0], sample, before_time) def test_disabled_project_in_list(self): project_id = uuid.uuid4().hex sample = dict() sample['project_id'] = unicode(project_id) before_time = timeutils.utcnow() self.revoke_api.revoke( model.RevokeEvent(project_id=project_id)) resp = self.get('/OS-REVOKE/events') events = resp.json_body['events'] self.assertEqual(len(events), 1) self.assertReportedEventMatchesRecorded(events[0], sample, before_time) def test_disabled_domain_in_list(self): domain_id = uuid.uuid4().hex sample = dict() sample['domain_id'] = unicode(domain_id) before_time = timeutils.utcnow() self.revoke_api.revoke( model.RevokeEvent(domain_id=domain_id)) resp = self.get('/OS-REVOKE/events') events = resp.json_body['events'] self.assertEqual(len(events), 1) self.assertReportedEventMatchesRecorded(events[0], sample, before_time) def test_list_since_invalid(self): self.get('/OS-REVOKE/events?since=blah', expected_status=400) def test_list_since_valid(self): resp = self.get('/OS-REVOKE/events?since=2013-02-27T18:30:59.999999Z') events = resp.json_body['events'] self.assertEqual(len(events), 0) def test_since_future_time_no_events(self): domain_id = uuid.uuid4().hex sample = dict() sample['domain_id'] = unicode(domain_id) self.revoke_api.revoke( model.RevokeEvent(domain_id=domain_id)) resp = self.get('/OS-REVOKE/events') events = resp.json_body['events'] self.assertEqual(len(events), 1) resp = self.get('/OS-REVOKE/events?since=%s' % _future_time_string()) events = resp.json_body['events'] self.assertEqual([], events) keystone-2014.1/keystone/tests/test_v3_filters.py0000664000175400017540000004144012323716272023304 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack LLC # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import tempfile import uuid from keystone import config from keystone.openstack.common import jsonutils from keystone.policy.backends import rules from keystone.tests import filtering from keystone.tests import test_v3 CONF = config.CONF class IdentityTestFilteredCase(filtering.FilterTests, test_v3.RestfulTestCase): """Test filter enforcement on the v3 Identity API.""" content_type = 'json' def setUp(self): """Setup for Identity Filter Test Cases.""" super(IdentityTestFilteredCase, self).setUp() # Initialize the policy engine and allow us to write to a temp # file in each test to create the policies self.orig_policy_file = CONF.policy_file rules.reset() _unused, self.tmpfilename = tempfile.mkstemp() self.config_fixture.config(policy_file=self.tmpfilename) #drop the policy rules self.addCleanup(rules.reset) def load_sample_data(self): """Create sample data for these tests. As well as the usual housekeeping, create a set of domains, users, roles and projects for the subsequent tests: - Three domains: A,B & C. C is disabled. - DomainA has user1, DomainB has user2 and user3 - DomainA has group1 and group2, DomainB has group3 - User1 has a role on DomainA Remember that there will also be a fourth domain in existence, the default domain. """ # Start by creating a few domains self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.domainC = self.new_domain_ref() self.domainC['enabled'] = False self.assignment_api.create_domain(self.domainC['id'], self.domainC) # Now create some users, one in domainA and two of them in domainB self.user1 = self.new_user_ref(domain_id=self.domainA['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref(domain_id=self.domainB['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user2['id'], self.user2) self.user3 = self.new_user_ref(domain_id=self.domainB['id']) self.user3['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user3['id'], self.user3) self.role = self.new_role_ref() self.assignment_api.create_role(self.role['id'], self.role) self.assignment_api.create_grant(self.role['id'], user_id=self.user1['id'], domain_id=self.domainA['id']) # A default auth request we can use - un-scoped user token self.auth = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password']) def _get_id_list_from_ref_list(self, ref_list): result_list = [] for x in ref_list: result_list.append(x['id']) return result_list def _set_policy(self, new_policy): with open(self.tmpfilename, "w") as policyfile: policyfile.write(jsonutils.dumps(new_policy)) def test_list_users_filtered_by_domain(self): """GET /users?domain_id=mydomain (filtered) Test Plan: - Update policy so api is unprotected - Use an un-scoped token to make sure we can filter the users by domainB, getting back the 2 users in that domain """ self._set_policy({"identity:list_users": []}) url_by_name = '/users?domain_id=%s' % self.domainB['id'] r = self.get(url_by_name, auth=self.auth) # We should get back two users, those in DomainB id_list = self._get_id_list_from_ref_list(r.result.get('users')) self.assertIn(self.user2['id'], id_list) self.assertIn(self.user3['id'], id_list) def test_list_filtered_domains(self): """GET /domains?enabled=0 Test Plan: - Update policy for no protection on api - Filter by the 'enabled' boolean to get disabled domains, which should return just domainC - Try the filter using different ways of specifying True/False to test that our handling of booleans in filter matching is correct """ new_policy = {"identity:list_domains": []} self._set_policy(new_policy) r = self.get('/domains?enabled=0', auth=self.auth) id_list = self._get_id_list_from_ref_list(r.result.get('domains')) self.assertEqual(len(id_list), 1) self.assertIn(self.domainC['id'], id_list) # Try a few ways of specifying 'false' for val in ('0', 'false', 'False', 'FALSE', 'n', 'no', 'off'): r = self.get('/domains?enabled=%s' % val, auth=self.auth) id_list = self._get_id_list_from_ref_list(r.result.get('domains')) self.assertEqual([self.domainC['id']], id_list) # Now try a few ways of specifying 'true' when we should get back # the other two domains, plus the default domain for val in ('1', 'true', 'True', 'TRUE', 'y', 'yes', 'on'): r = self.get('/domains?enabled=%s' % val, auth=self.auth) id_list = self._get_id_list_from_ref_list(r.result.get('domains')) self.assertEqual(len(id_list), 3) self.assertIn(self.domainA['id'], id_list) self.assertIn(self.domainB['id'], id_list) self.assertIn(CONF.identity.default_domain_id, id_list) r = self.get('/domains?enabled', auth=self.auth) id_list = self._get_id_list_from_ref_list(r.result.get('domains')) self.assertEqual(len(id_list), 3) self.assertIn(self.domainA['id'], id_list) self.assertIn(self.domainB['id'], id_list) self.assertIn(CONF.identity.default_domain_id, id_list) def test_multiple_filters(self): """GET /domains?enabled&name=myname Test Plan: - Update policy for no protection on api - Filter by the 'enabled' boolean and name - this should return a single domain """ new_policy = {"identity:list_domains": []} self._set_policy(new_policy) my_url = '/domains?enableds&name=%s' % self.domainA['name'] r = self.get(my_url, auth=self.auth) id_list = self._get_id_list_from_ref_list(r.result.get('domains')) self.assertEqual(len(id_list), 1) self.assertIn(self.domainA['id'], id_list) def test_list_users_filtered_by_funny_name(self): """GET /users?name=%myname% Test Plan: - Update policy so api is unprotected - Update a user with name that has filter escape characters - Ensure we can filter on it """ self._set_policy({"identity:list_users": []}) user = self.user1 user['name'] = '%my%name%' self.identity_api.update_user(user['id'], user) url_by_name = '/users?name=%my%name%' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 1) self.assertEqual(r.result.get('users')[0]['id'], user['id']) def test_inexact_filters(self): # Create 20 users user_list = self._create_test_data('user', 20) # Set up some names that we can filter on user = user_list[5] user['name'] = 'The' self.identity_api.update_user(user['id'], user) user = user_list[6] user['name'] = 'The Ministry' self.identity_api.update_user(user['id'], user) user = user_list[7] user['name'] = 'The Ministry of' self.identity_api.update_user(user['id'], user) user = user_list[8] user['name'] = 'The Ministry of Silly' self.identity_api.update_user(user['id'], user) user = user_list[9] user['name'] = 'The Ministry of Silly Walks' self.identity_api.update_user(user['id'], user) # ...and one for useful case insensitivity testing user = user_list[10] user['name'] = 'the ministry of silly walks OF' self.identity_api.update_user(user['id'], user) self._set_policy({"identity:list_users": []}) url_by_name = '/users?name__contains=Ministry' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 4) self._match_with_list(r.result.get('users'), user_list, list_start=6, list_end=10) url_by_name = '/users?name__icontains=miNIstry' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 5) self._match_with_list(r.result.get('users'), user_list, list_start=6, list_end=11) url_by_name = '/users?name__startswith=The' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 5) self._match_with_list(r.result.get('users'), user_list, list_start=5, list_end=10) url_by_name = '/users?name__istartswith=the' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 6) self._match_with_list(r.result.get('users'), user_list, list_start=5, list_end=11) url_by_name = '/users?name__endswith=of' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 1) self.assertEqual(r.result.get('users')[0]['id'], user_list[7]['id']) url_by_name = '/users?name__iendswith=OF' r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 2) self.assertEqual(r.result.get('users')[0]['id'], user_list[7]['id']) self.assertEqual(r.result.get('users')[1]['id'], user_list[10]['id']) self._delete_test_data('user', user_list) def test_filter_sql_injection_attack(self): """GET /users?name= Test Plan: - Attempt to get all entities back by passing a two-term attribute - Attempt to piggyback filter to damage DB (e.g. drop table) """ self._set_policy({"identity:list_users": [], "identity:list_groups": [], "identity:create_group": []}) url_by_name = "/users?name=anything' or 'x'='x" r = self.get(url_by_name, auth=self.auth) self.assertEqual(len(r.result.get('users')), 0) # See if we can add a SQL command...use the group table instead of the # user table since 'user' is reserved word for SQLAlchemy. group = self.new_group_ref(domain_id=self.domainB['id']) self.identity_api.create_group(group['id'], group) url_by_name = "/users?name=x'; drop table group" r = self.get(url_by_name, auth=self.auth) # Check group table is still there... url_by_name = "/groups" r = self.get(url_by_name, auth=self.auth) self.assertTrue(len(r.result.get('groups')) > 0) class IdentityTestListLimitCase(IdentityTestFilteredCase): """Test list limiting enforcement on the v3 Identity API.""" content_type = 'json' def setUp(self): """Setup for Identity Limit Test Cases.""" super(IdentityTestListLimitCase, self).setUp() self._set_policy({"identity:list_users": [], "identity:list_groups": [], "identity:list_projects": [], "identity:list_services": [], "identity:list_policies": []}) # Create 10 entries for each of the entities we are going to test self.ENTITY_TYPES = ['user', 'group', 'project'] self.entity_lists = {} for entity in self.ENTITY_TYPES: self.entity_lists[entity] = self._create_test_data(entity, 10) # Make sure we clean up when finished self.addCleanup(self.clean_up_entity, entity) self.service_list = [] self.addCleanup(self.clean_up_service) for _ in range(10): new_entity = {'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex} service = self.catalog_api.create_service(new_entity['id'], new_entity) self.service_list.append(service) self.policy_list = [] self.addCleanup(self.clean_up_policy) for _ in range(10): new_entity = {'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'blob': uuid.uuid4().hex} policy = self.policy_api.create_policy(new_entity['id'], new_entity) self.policy_list.append(policy) def clean_up_entity(self, entity): """Clean up entity test data from Identity Limit Test Cases.""" self._delete_test_data(entity, self.entity_lists[entity]) def clean_up_service(self): """Clean up service test data from Identity Limit Test Cases.""" for service in self.service_list: self.catalog_api.delete_service(service['id']) def clean_up_policy(self): """Clean up policy test data from Identity Limit Test Cases.""" for policy in self.policy_list: self.policy_api.delete_policy(policy['id']) def _test_entity_list_limit(self, entity, driver): """GET / (limited) Test Plan: - For the specified type of entity: - Update policy for no protection on api - Add a bunch of entities - Set the global list limit to 5, and check that getting all - entities only returns 5 - Set the driver list_limit to 4, and check that now only 4 are - returned """ if entity == 'policy': plural = 'policies' else: plural = '%ss' % entity self.config_fixture.config(list_limit=5) self.config_fixture.config(group=driver, list_limit=None) r = self.get('/%s' % plural, auth=self.auth) self.assertEqual(len(r.result.get(plural)), 5) self.assertIs(r.result.get('truncated'), True) self.config_fixture.config(group=driver, list_limit=4) r = self.get('/%s' % plural, auth=self.auth) self.assertEqual(len(r.result.get(plural)), 4) self.assertIs(r.result.get('truncated'), True) def test_users_list_limit(self): self._test_entity_list_limit('user', 'identity') def test_groups_list_limit(self): self._test_entity_list_limit('group', 'identity') def test_projects_list_limit(self): self._test_entity_list_limit('project', 'assignment') def test_services_list_limit(self): self._test_entity_list_limit('service', 'catalog') def test_non_driver_list_limit(self): """Check list can be limited without driver level support. Policy limiting is not done at the driver level (since it really isn't worth doing it there). So use this as a test for ensuring the controller level will successfully limit in this case. """ self._test_entity_list_limit('policy', 'policy') def test_no_limit(self): """Check truncated attribute not set when list not limited.""" r = self.get('/services', auth=self.auth) self.assertEqual(len(r.result.get('services')), 10) self.assertIsNone(r.result.get('truncated')) def test_at_limit(self): """Check truncated attribute not set when list at max size.""" # Test this by overriding the general limit with a higher # driver-specific limit (allowing all entities to be returned # in the collection), which should result in a non truncated list self.config_fixture.config(list_limit=5) self.config_fixture.config(group='catalog', list_limit=10) r = self.get('/services', auth=self.auth) self.assertEqual(len(r.result.get('services')), 10) self.assertIsNone(r.result.get('truncated')) class IdentityTestFilteredCaseXML(IdentityTestFilteredCase): content_type = 'xml' class IdentityTestListLimitCaseXML(IdentityTestListLimitCase): content_type = 'xml' keystone-2014.1/keystone/tests/test_base64utils.py0000664000175400017540000002036412323716272023373 0ustar jenkinsjenkins00000000000000# Copyright 2013 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 keystone.common import base64utils from keystone import tests base64_alphabet = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' '0123456789' '+/=') # includes pad char base64url_alphabet = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' '0123456789' '-_=') # includes pad char class TestValid(tests.TestCase): def test_valid_base64(self): self.assertTrue(base64utils.is_valid_base64('+/==')) self.assertTrue(base64utils.is_valid_base64('+/+=')) self.assertTrue(base64utils.is_valid_base64('+/+/')) self.assertFalse(base64utils.is_valid_base64('-_==')) self.assertFalse(base64utils.is_valid_base64('-_-=')) self.assertFalse(base64utils.is_valid_base64('-_-_')) self.assertTrue(base64utils.is_valid_base64('abcd')) self.assertFalse(base64utils.is_valid_base64('abcde')) self.assertFalse(base64utils.is_valid_base64('abcde==')) self.assertFalse(base64utils.is_valid_base64('abcdef')) self.assertTrue(base64utils.is_valid_base64('abcdef==')) self.assertFalse(base64utils.is_valid_base64('abcdefg')) self.assertTrue(base64utils.is_valid_base64('abcdefg=')) self.assertTrue(base64utils.is_valid_base64('abcdefgh')) self.assertFalse(base64utils.is_valid_base64('-_==')) def test_valid_base64url(self): self.assertFalse(base64utils.is_valid_base64url('+/==')) self.assertFalse(base64utils.is_valid_base64url('+/+=')) self.assertFalse(base64utils.is_valid_base64url('+/+/')) self.assertTrue(base64utils.is_valid_base64url('-_==')) self.assertTrue(base64utils.is_valid_base64url('-_-=')) self.assertTrue(base64utils.is_valid_base64url('-_-_')) self.assertTrue(base64utils.is_valid_base64url('abcd')) self.assertFalse(base64utils.is_valid_base64url('abcde')) self.assertFalse(base64utils.is_valid_base64url('abcde==')) self.assertFalse(base64utils.is_valid_base64url('abcdef')) self.assertTrue(base64utils.is_valid_base64url('abcdef==')) self.assertFalse(base64utils.is_valid_base64url('abcdefg')) self.assertTrue(base64utils.is_valid_base64url('abcdefg=')) self.assertTrue(base64utils.is_valid_base64url('abcdefgh')) self.assertTrue(base64utils.is_valid_base64url('-_==')) class TestBase64Padding(tests.TestCase): def test_filter(self): self.assertEqual(base64utils.filter_formatting(''), '') self.assertEqual(base64utils.filter_formatting(' '), '') self.assertEqual(base64utils.filter_formatting('a'), 'a') self.assertEqual(base64utils.filter_formatting(' a'), 'a') self.assertEqual(base64utils.filter_formatting('a '), 'a') self.assertEqual(base64utils.filter_formatting('ab'), 'ab') self.assertEqual(base64utils.filter_formatting(' ab'), 'ab') self.assertEqual(base64utils.filter_formatting('ab '), 'ab') self.assertEqual(base64utils.filter_formatting('a b'), 'ab') self.assertEqual(base64utils.filter_formatting(' a b'), 'ab') self.assertEqual(base64utils.filter_formatting('a b '), 'ab') self.assertEqual(base64utils.filter_formatting('a\nb\n '), 'ab') text = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' '0123456789' '+/=') self.assertEqual(base64_alphabet, base64utils.filter_formatting(text)) text = (' ABCDEFGHIJKLMNOPQRSTUVWXYZ\n' ' abcdefghijklmnopqrstuvwxyz\n' '\t\f\r' ' 0123456789\n' ' +/=') self.assertEqual(base64_alphabet, base64utils.filter_formatting(text)) self.assertEqual(base64url_alphabet, base64utils.base64_to_base64url(base64_alphabet)) text = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' '0123456789' '-_=') self.assertEqual(base64url_alphabet, base64utils.filter_formatting(text)) text = (' ABCDEFGHIJKLMNOPQRSTUVWXYZ\n' ' abcdefghijklmnopqrstuvwxyz\n' '\t\f\r' ' 0123456789\n' '-_=') self.assertEqual(base64url_alphabet, base64utils.filter_formatting(text)) def test_alphabet_conversion(self): self.assertEqual(base64url_alphabet, base64utils.base64_to_base64url(base64_alphabet)) self.assertEqual(base64_alphabet, base64utils.base64url_to_base64(base64url_alphabet)) def test_is_padded(self): self.assertTrue(base64utils.base64_is_padded('ABCD')) self.assertTrue(base64utils.base64_is_padded('ABC=')) self.assertTrue(base64utils.base64_is_padded('AB==')) self.assertTrue(base64utils.base64_is_padded('1234ABCD')) self.assertTrue(base64utils.base64_is_padded('1234ABC=')) self.assertTrue(base64utils.base64_is_padded('1234AB==')) self.assertFalse(base64utils.base64_is_padded('ABC')) self.assertFalse(base64utils.base64_is_padded('AB')) self.assertFalse(base64utils.base64_is_padded('A')) self.assertFalse(base64utils.base64_is_padded('')) self.assertRaises(base64utils.InvalidBase64Error, base64utils.base64_is_padded, '=') self.assertRaises(base64utils.InvalidBase64Error, base64utils.base64_is_padded, 'AB=C') self.assertRaises(base64utils.InvalidBase64Error, base64utils.base64_is_padded, 'AB=') self.assertRaises(base64utils.InvalidBase64Error, base64utils.base64_is_padded, 'ABCD=') def test_strip_padding(self): self.assertEqual(base64utils.base64_strip_padding('ABCD'), 'ABCD') self.assertEqual(base64utils.base64_strip_padding('ABC='), 'ABC') self.assertEqual(base64utils.base64_strip_padding('AB=='), 'AB') def test_assure_padding(self): self.assertEqual(base64utils.base64_assure_padding('ABCD'), 'ABCD') self.assertEqual(base64utils.base64_assure_padding('ABC'), 'ABC=') self.assertEqual(base64utils.base64_assure_padding('ABC='), 'ABC=') self.assertEqual(base64utils.base64_assure_padding('AB'), 'AB==') self.assertEqual(base64utils.base64_assure_padding('AB=='), 'AB==') def test_base64_percent_encoding(self): self.assertEqual(base64utils.base64url_percent_encode('ABCD'), 'ABCD') self.assertEqual(base64utils.base64url_percent_encode('ABC='), 'ABC%3D') self.assertEqual(base64utils.base64url_percent_encode('AB=='), 'AB%3D%3D') self.assertEqual(base64utils.base64url_percent_decode('ABCD'), 'ABCD') self.assertEqual(base64utils.base64url_percent_decode('ABC%3D'), 'ABC=') self.assertEqual(base64utils.base64url_percent_decode('AB%3D%3D'), 'AB==') class TestTextWrap(tests.TestCase): def test_wrapping(self): raw_text = 'abcdefgh' wrapped_text = 'abc\ndef\ngh\n' self.assertEqual(base64utils.base64_wrap(raw_text, width=3), wrapped_text) t = '\n'.join(base64utils.base64_wrap_iter(raw_text, width=3)) + '\n' self.assertEqual(t, wrapped_text) raw_text = 'abcdefgh' wrapped_text = 'abcd\nefgh\n' self.assertEqual(base64utils.base64_wrap(raw_text, width=4), wrapped_text) keystone-2014.1/keystone/tests/test_kvs.py0000664000175400017540000006051512323716272022033 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, 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. import time import uuid from dogpile.cache import api from dogpile.cache import proxy from dogpile.cache import util import mock import six from testtools import matchers from keystone.common.kvs.backends import inmemdb from keystone.common.kvs.backends import memcached from keystone.common.kvs import core from keystone import exception from keystone import tests NO_VALUE = api.NO_VALUE class MutexFixture(object): def __init__(self, storage_dict, key, timeout): self.database = storage_dict self.key = '_lock' + key self.lock_timeout = timeout def acquire(self, wait=True): while True: try: self.database[self.key] = 1 return True except KeyError: return False def release(self): self.database.pop(self.key, None) class KVSBackendFixture(inmemdb.MemoryBackend): def __init__(self, arguments): class InmemTestDB(dict): def __setitem__(self, key, value): if key in self: raise KeyError('Key %s already exists' % key) super(InmemTestDB, self).__setitem__(key, value) self._db = InmemTestDB() self.lock_timeout = arguments.pop('lock_timeout', 5) self.test_arg = arguments.pop('test_arg', None) def get_mutex(self, key): return MutexFixture(self._db, key, self.lock_timeout) @classmethod def key_mangler(cls, key): return 'KVSBackend_' + key class KVSBackendForcedKeyMangleFixture(KVSBackendFixture): use_backend_key_mangler = True @classmethod def key_mangler(cls, key): return 'KVSBackendForcedKeyMangle_' + key class RegionProxyFixture(proxy.ProxyBackend): """A test dogpile.cache proxy that does nothing.""" class RegionProxy2Fixture(proxy.ProxyBackend): """A test dogpile.cache proxy that does nothing.""" class TestMemcacheDriver(api.CacheBackend): """A test dogpile.cache backend that conforms to the mixin-mechanism for overriding set and set_multi methods on dogpile memcached drivers. """ class test_client(object): # FIXME(morganfainberg): Convert this test client over to using mock # and/or mock.MagicMock as appropriate def __init__(self): self.__name__ = 'TestingMemcacheDriverClientObject' self.set_arguments_passed = None self.keys_values = {} self.lock_set_time = None self.lock_expiry = None def set(self, key, value, **set_arguments): self.keys_values.clear() self.keys_values[key] = value self.set_arguments_passed = set_arguments def set_multi(self, mapping, **set_arguments): self.keys_values.clear() self.keys_values = mapping self.set_arguments_passed = set_arguments def add(self, key, value, expiry_time): # NOTE(morganfainberg): `add` is used in this case for the # memcache lock testing. If further testing is required around the # actual memcache `add` interface, this method should be # expanded to work more like the actual memcache `add` function if self.lock_expiry is not None and self.lock_set_time is not None: if time.time() - self.lock_set_time < self.lock_expiry: return False self.lock_expiry = expiry_time self.lock_set_time = time.time() return True def delete(self, key): # NOTE(morganfainberg): `delete` is used in this case for the # memcache lock testing. If further testing is required around the # actual memcache `delete` interface, this method should be # expanded to work more like the actual memcache `delete` function. self.lock_expiry = None self.lock_set_time = None return True def __init__(self, arguments): self.client = self.test_client() self.set_arguments = {} # NOTE(morganfainberg): This is the same logic as the dogpile backend # since we need to mirror that functionality for the `set_argument` # values to appear on the actual backend. if 'memcached_expire_time' in arguments: self.set_arguments['time'] = arguments['memcached_expire_time'] def set(self, key, value): self.client.set(key, value, **self.set_arguments) def set_multi(self, mapping): self.client.set_multi(mapping, **self.set_arguments) class KVSTest(tests.TestCase): def setUp(self): super(KVSTest, self).setUp() self.key_foo = 'foo_' + uuid.uuid4().hex self.value_foo = uuid.uuid4().hex self.key_bar = 'bar_' + uuid.uuid4().hex self.value_bar = {'complex_data_structure': uuid.uuid4().hex} self.addCleanup(memcached.VALID_DOGPILE_BACKENDS.pop, 'TestDriver', None) memcached.VALID_DOGPILE_BACKENDS['TestDriver'] = TestMemcacheDriver def _get_kvs_region(self, name=None): if name is None: name = uuid.uuid4().hex return core.get_key_value_store(name) def test_kvs_basic_configuration(self): # Test that the most basic configuration options pass through to the # backend. region_one = uuid.uuid4().hex region_two = uuid.uuid4().hex test_arg = 100 kvs = self._get_kvs_region(region_one) kvs.configure('openstack.kvs.Memory') self.assertIsInstance(kvs._region.backend, inmemdb.MemoryBackend) self.assertEqual(kvs._region.name, region_one) kvs = self._get_kvs_region(region_two) kvs.configure('openstack.kvs.KVSBackendFixture', test_arg=test_arg) self.assertEqual(kvs._region.name, region_two) self.assertEqual(kvs._region.backend.test_arg, test_arg) def test_kvs_proxy_configuration(self): # Test that proxies are applied correctly and in the correct (reverse) # order to the kvs region. kvs = self._get_kvs_region() kvs.configure( 'openstack.kvs.Memory', proxy_list=['keystone.tests.test_kvs.RegionProxyFixture', 'keystone.tests.test_kvs.RegionProxy2Fixture']) self.assertIsInstance(kvs._region.backend, RegionProxyFixture) self.assertIsInstance(kvs._region.backend.proxied, RegionProxy2Fixture) self.assertIsInstance(kvs._region.backend.proxied.proxied, inmemdb.MemoryBackend) def test_kvs_key_mangler_fallthrough_default(self): # Test to make sure we default to the standard dogpile sha1 hashing # key_mangler kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') self.assertIs(kvs._region.key_mangler, util.sha1_mangle_key) # The backend should also have the keymangler set the same as the # region now. self.assertIs(kvs._region.backend.key_mangler, util.sha1_mangle_key) def test_kvs_key_mangler_configuration_backend(self): kvs = self._get_kvs_region() kvs.configure('openstack.kvs.KVSBackendFixture') expected = KVSBackendFixture.key_mangler(self.key_foo) self.assertEqual(expected, kvs._region.key_mangler(self.key_foo)) def test_kvs_key_mangler_configuration_forced_backend(self): kvs = self._get_kvs_region() kvs.configure('openstack.kvs.KVSBackendForcedKeyMangleFixture', key_mangler=util.sha1_mangle_key) expected = KVSBackendForcedKeyMangleFixture.key_mangler(self.key_foo) self.assertEqual(expected, kvs._region.key_mangler(self.key_foo)) def test_kvs_key_mangler_configuration_disabled(self): # Test that no key_mangler is set if enable_key_mangler is false self.config_fixture.config(group='kvs', enable_key_mangler=False) kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') self.assertIsNone(kvs._region.key_mangler) self.assertIsNone(kvs._region.backend.key_mangler) def test_kvs_key_mangler_set_on_backend(self): def test_key_mangler(key): return key kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') self.assertIs(kvs._region.backend.key_mangler, util.sha1_mangle_key) kvs._set_key_mangler(test_key_mangler) self.assertIs(kvs._region.backend.key_mangler, test_key_mangler) def test_kvs_basic_get_set_delete(self): # Test the basic get/set/delete actions on the KVS region kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') # Not found should be raised if the key doesn't exist self.assertRaises(exception.NotFound, kvs.get, key=self.key_bar) kvs.set(self.key_bar, self.value_bar) returned_value = kvs.get(self.key_bar) # The returned value should be the same value as the value in .set self.assertEqual(returned_value, self.value_bar) # The value should not be the exact object used in .set self.assertIsNot(returned_value, self.value_bar) kvs.delete(self.key_bar) # Second delete should raise NotFound self.assertRaises(exception.NotFound, kvs.delete, key=self.key_bar) def _kvs_multi_get_set_delete(self, kvs): keys = [self.key_foo, self.key_bar] expected = [self.value_foo, self.value_bar] kvs.set_multi({self.key_foo: self.value_foo, self.key_bar: self.value_bar}) # Returned value from get_multi should be a list of the values of the # keys self.assertEqual(kvs.get_multi(keys), expected) # Delete both keys kvs.delete_multi(keys) # make sure that NotFound is properly raised when trying to get the now # deleted keys self.assertRaises(exception.NotFound, kvs.get_multi, keys=keys) self.assertRaises(exception.NotFound, kvs.get, key=self.key_foo) self.assertRaises(exception.NotFound, kvs.get, key=self.key_bar) # Make sure get_multi raises NotFound if one of the keys isn't found kvs.set(self.key_foo, self.value_foo) self.assertRaises(exception.NotFound, kvs.get_multi, keys=keys) def test_kvs_multi_get_set_delete(self): kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') self._kvs_multi_get_set_delete(kvs) def test_kvs_locking_context_handler(self): # Make sure we're creating the correct key/value pairs for the backend # distributed locking mutex. self.config_fixture.config(group='kvs', enable_key_mangler=False) kvs = self._get_kvs_region() kvs.configure('openstack.kvs.KVSBackendFixture') lock_key = '_lock' + self.key_foo self.assertNotIn(lock_key, kvs._region.backend._db) with core.KeyValueStoreLock(kvs._mutex(self.key_foo), self.key_foo): self.assertIn(lock_key, kvs._region.backend._db) self.assertIs(kvs._region.backend._db[lock_key], 1) self.assertNotIn(lock_key, kvs._region.backend._db) def test_kvs_locking_context_handler_locking_disabled(self): # Make sure no creation of key/value pairs for the backend # distributed locking mutex occurs if locking is disabled. self.config_fixture.config(group='kvs', enable_key_mangler=False) kvs = self._get_kvs_region() kvs.configure('openstack.kvs.KVSBackendFixture', locking=False) lock_key = '_lock' + self.key_foo self.assertNotIn(lock_key, kvs._region.backend._db) with core.KeyValueStoreLock(kvs._mutex(self.key_foo), self.key_foo, False): self.assertNotIn(lock_key, kvs._region.backend._db) self.assertNotIn(lock_key, kvs._region.backend._db) def test_kvs_with_lock_action_context_manager_timeout(self): kvs = self._get_kvs_region() lock_timeout = 5 kvs.configure('openstack.kvs.Memory', lock_timeout=lock_timeout) def do_with_lock_action_timeout(kvs_region, key, offset): with kvs_region.get_lock(key) as lock_in_use: self.assertTrue(lock_in_use.active) # Subtract the offset from the acquire_time. If this puts the # acquire_time difference from time.time() at >= lock_timeout # this should raise a LockTimeout exception. This is because # there is a built-in 1-second overlap where the context # manager thinks the lock is expired but the lock is still # active. This is to help mitigate race conditions on the # time-check itself. lock_in_use.acquire_time -= offset with kvs_region._action_with_lock(key, lock_in_use): pass # This should succeed, we are not timed-out here. do_with_lock_action_timeout(kvs, key=uuid.uuid4().hex, offset=2) # Try it now with an offset equal to the lock_timeout self.assertRaises(core.LockTimeout, do_with_lock_action_timeout, kvs_region=kvs, key=uuid.uuid4().hex, offset=lock_timeout) # Final test with offset significantly greater than the lock_timeout self.assertRaises(core.LockTimeout, do_with_lock_action_timeout, kvs_region=kvs, key=uuid.uuid4().hex, offset=100) def test_kvs_with_lock_action_mismatched_keys(self): kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') def do_with_lock_action(kvs_region, lock_key, target_key): with kvs_region.get_lock(lock_key) as lock_in_use: self.assertTrue(lock_in_use.active) with kvs_region._action_with_lock(target_key, lock_in_use): pass # Ensure we raise a ValueError if the lock key mismatches from the # target key. self.assertRaises(ValueError, do_with_lock_action, kvs_region=kvs, lock_key=self.key_foo, target_key=self.key_bar) def test_kvs_with_lock_action_context_manager(self): # Make sure we're creating the correct key/value pairs for the backend # distributed locking mutex. self.config_fixture.config(group='kvs', enable_key_mangler=False) kvs = self._get_kvs_region() kvs.configure('openstack.kvs.KVSBackendFixture') lock_key = '_lock' + self.key_foo self.assertNotIn(lock_key, kvs._region.backend._db) with kvs.get_lock(self.key_foo) as lock: with kvs._action_with_lock(self.key_foo, lock): self.assertTrue(lock.active) self.assertIn(lock_key, kvs._region.backend._db) self.assertIs(kvs._region.backend._db[lock_key], 1) self.assertNotIn(lock_key, kvs._region.backend._db) def test_kvs_with_lock_action_context_manager_no_lock(self): # Make sure we're not locking unless an actual lock is passed into the # context manager self.config_fixture.config(group='kvs', enable_key_mangler=False) kvs = self._get_kvs_region() kvs.configure('openstack.kvs.KVSBackendFixture') lock_key = '_lock' + self.key_foo lock = None self.assertNotIn(lock_key, kvs._region.backend._db) with kvs._action_with_lock(self.key_foo, lock): self.assertNotIn(lock_key, kvs._region.backend._db) self.assertNotIn(lock_key, kvs._region.backend._db) def test_kvs_backend_registration_does_not_reregister_backends(self): # SetUp registers the test backends. Running this again would raise an # exception if re-registration of the backends occurred. kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memory') core._register_backends() def test_kvs_memcached_manager_valid_dogpile_memcached_backend(self): kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memcached', memcached_backend='TestDriver') self.assertIsInstance(kvs._region.backend.driver, TestMemcacheDriver) def test_kvs_memcached_manager_invalid_dogpile_memcached_backend(self): # Invalid dogpile memcache backend should raise ValueError kvs = self._get_kvs_region() self.assertRaises(ValueError, kvs.configure, backing_store='openstack.kvs.Memcached', memcached_backend=uuid.uuid4().hex) def test_kvs_memcache_manager_no_expiry_keys(self): # Make sure the memcache backend recalculates the no-expiry keys # correctly when a key-mangler is set on it. def new_mangler(key): return '_mangled_key_' + key kvs = self._get_kvs_region() no_expiry_keys = set(['test_key']) kvs.configure('openstack.kvs.Memcached', memcached_backend='TestDriver', no_expiry_keys=no_expiry_keys) calculated_keys = set([kvs._region.key_mangler(key) for key in no_expiry_keys]) self.assertIs(kvs._region.backend.key_mangler, util.sha1_mangle_key) self.assertSetEqual(calculated_keys, kvs._region.backend.no_expiry_hashed_keys) self.assertSetEqual(no_expiry_keys, kvs._region.backend.raw_no_expiry_keys) calculated_keys = set([new_mangler(key) for key in no_expiry_keys]) kvs._region.backend.key_mangler = new_mangler self.assertSetEqual(calculated_keys, kvs._region.backend.no_expiry_hashed_keys) self.assertSetEqual(no_expiry_keys, kvs._region.backend.raw_no_expiry_keys) def test_kvs_memcache_key_mangler_set_to_none(self): kvs = self._get_kvs_region() no_expiry_keys = set(['test_key']) kvs.configure('openstack.kvs.Memcached', memcached_backend='TestDriver', no_expiry_keys=no_expiry_keys) self.assertIs(kvs._region.backend.key_mangler, util.sha1_mangle_key) kvs._region.backend.key_mangler = None self.assertSetEqual(kvs._region.backend.raw_no_expiry_keys, kvs._region.backend.no_expiry_hashed_keys) self.assertIsNone(kvs._region.backend.key_mangler) def test_noncallable_key_mangler_set_on_driver_raises_type_error(self): kvs = self._get_kvs_region() kvs.configure('openstack.kvs.Memcached', memcached_backend='TestDriver') self.assertRaises(TypeError, setattr, kvs._region.backend, 'key_mangler', 'Non-Callable') def test_kvs_memcache_set_arguments_and_memcache_expires_ttl(self): # Test the "set_arguments" (arguments passed on all set calls) logic # and the no-expiry-key modifications of set_arguments for the explicit # memcache TTL. self.config_fixture.config(group='kvs', enable_key_mangler=False) kvs = self._get_kvs_region() memcache_expire_time = 86400 expected_set_args = {'time': memcache_expire_time} expected_no_expiry_args = {} expected_foo_keys = [self.key_foo] expected_bar_keys = [self.key_bar] mapping_foo = dict([(self.key_foo, self.value_foo)]) mapping_bar = dict([(self.key_bar, self.value_bar)]) kvs.configure(backing_store='openstack.kvs.Memcached', memcached_backend='TestDriver', memcached_expire_time=memcache_expire_time, some_other_arg=uuid.uuid4().hex, no_expiry_keys=[self.key_bar]) # Ensure the set_arguments are correct self.assertDictEqual( kvs._region.backend._get_set_arguments_driver_attr(), expected_set_args) # Set a key that would have an expiry and verify the correct result # occurred and that the correct set_arguments were passed. kvs.set(self.key_foo, self.value_foo) self.assertDictEqual( kvs._region.backend.driver.client.set_arguments_passed, expected_set_args) self.assertEqual(kvs._region.backend.driver.client.keys_values.keys(), expected_foo_keys) self.assertEqual( kvs._region.backend.driver.client.keys_values[self.key_foo][0], self.value_foo) # Set a key that would not have an expiry and verify the correct result # occurred and that the correct set_arguments were passed. kvs.set(self.key_bar, self.value_bar) self.assertDictEqual( kvs._region.backend.driver.client.set_arguments_passed, expected_no_expiry_args) self.assertEqual(kvs._region.backend.driver.client.keys_values.keys(), expected_bar_keys) self.assertEqual( kvs._region.backend.driver.client.keys_values[self.key_bar][0], self.value_bar) # set_multi a dict that would have an expiry and verify the correct # result occurred and that the correct set_arguments were passed. kvs.set_multi(mapping_foo) self.assertDictEqual( kvs._region.backend.driver.client.set_arguments_passed, expected_set_args) self.assertEqual(kvs._region.backend.driver.client.keys_values.keys(), expected_foo_keys) self.assertEqual( kvs._region.backend.driver.client.keys_values[self.key_foo][0], self.value_foo) # set_multi a dict that would not have an expiry and verify the correct # result occurred and that the correct set_arguments were passed. kvs.set_multi(mapping_bar) self.assertDictEqual( kvs._region.backend.driver.client.set_arguments_passed, expected_no_expiry_args) self.assertEqual(kvs._region.backend.driver.client.keys_values.keys(), expected_bar_keys) self.assertEqual( kvs._region.backend.driver.client.keys_values[self.key_bar][0], self.value_bar) def test_memcached_lock_max_lock_attempts(self): kvs = self._get_kvs_region() max_lock_attempts = 1 test_key = uuid.uuid4().hex kvs.configure(backing_store='openstack.kvs.Memcached', memcached_backend='TestDriver', max_lock_attempts=max_lock_attempts) self.assertEqual(kvs._region.backend.max_lock_attempts, max_lock_attempts) # Simple Lock success test with kvs.get_lock(test_key) as lock: kvs.set(test_key, 'testing', lock) def lock_within_a_lock(key): with kvs.get_lock(key) as first_lock: kvs.set(test_key, 'lock', first_lock) with kvs.get_lock(key) as second_lock: kvs.set(key, 'lock-within-a-lock', second_lock) self.assertRaises(exception.UnexpectedError, lock_within_a_lock, key=test_key) class TestMemcachedBackend(tests.TestCase): @mock.patch('keystone.common.kvs.backends.memcached._', six.text_type) def test_invalid_backend_fails_initialization(self): raises_valueerror = matchers.Raises(matchers.MatchesException( ValueError, r'.*FakeBackend.*')) options = { 'url': 'needed to get to the focus of this test (the backend)', 'memcached_backend': 'FakeBackend', } self.assertThat(lambda: memcached.MemcachedBackend(options), raises_valueerror) keystone-2014.1/keystone/tests/test_ssl.py0000664000175400017540000001345512323716267022036 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import os import ssl from keystone.common import environment from keystone import config from keystone import tests from keystone.tests.ksfixtures import appserver CONF = config.CONF CERTDIR = tests.dirs.root('examples', 'pki', 'certs') KEYDIR = tests.dirs.root('examples', 'pki', 'private') CERT = os.path.join(CERTDIR, 'ssl_cert.pem') KEY = os.path.join(KEYDIR, 'ssl_key.pem') CA = os.path.join(CERTDIR, 'cacert.pem') CLIENT = os.path.join(CERTDIR, 'middleware.pem') class SSLTestCase(tests.TestCase): def setUp(self): super(SSLTestCase, self).setUp() self.load_backends() def test_1way_ssl_ok(self): """Make sure both public and admin API work with 1-way SSL.""" paste_conf = self._paste_config('keystone') ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA) # Verify Admin with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.admin_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) # Verify Public with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.public_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) def test_2way_ssl_ok(self): """Make sure both public and admin API work with 2-way SSL. Requires client certificate. """ paste_conf = self._paste_config('keystone') ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, cert_required=True) # Verify Admin with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.admin_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) # Verify Public with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.public_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) def test_1way_ssl_with_ipv6_ok(self): """Make sure both public and admin API work with 1-way ipv6 & SSL.""" self.skip_if_no_ipv6() paste_conf = self._paste_config('keystone') ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, host="::1") # Verify Admin with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection('::1', CONF.admin_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) # Verify Public with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection('::1', CONF.public_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) def test_2way_ssl_with_ipv6_ok(self): """Make sure both public and admin API work with 2-way ipv6 & SSL. Requires client certificate. """ self.skip_if_no_ipv6() paste_conf = self._paste_config('keystone') ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, cert_required=True, host="::1") # Verify Admin with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '::1', CONF.admin_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) # Verify Public with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '::1', CONF.public_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(300, resp.status) def test_2way_ssl_fail(self): """Expect to fail when client does not present proper certificate.""" paste_conf = self._paste_config('keystone') ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, cert_required=True) # Verify Admin with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.admin_port) try: conn.request('GET', '/') self.fail('Admin API shoulda failed with SSL handshake!') except ssl.SSLError: pass # Verify Public with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs): conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.public_port) try: conn.request('GET', '/') self.fail('Public API shoulda failed with SSL handshake!') except ssl.SSLError: pass keystone-2014.1/keystone/tests/test_v3_auth.py0000664000175400017540000036753212323716272022612 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import copy import datetime import json import uuid from keystoneclient.common import cms from keystone import auth from keystone.common import dependency from keystone import config from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import test_v3 CONF = config.CONF class TestAuthInfo(test_v3.RestfulTestCase): # TODO(henry-nash) These tests are somewhat inefficient, since by # using the test_v3.RestfulTestCase class to gain access to the auth # building helper functions, they cause backend databases and fixtures # to be loaded unnecessarily. Separating out the helper functions from # this base class would improve efficiency (Bug #1134836) def test_missing_auth_methods(self): auth_data = {'identity': {}} auth_data['identity']['token'] = {'id': uuid.uuid4().hex} self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo.create, None, auth_data) def test_unsupported_auth_method(self): auth_data = {'methods': ['abc']} auth_data['abc'] = {'test': 'test'} auth_data = {'identity': auth_data} self.assertRaises(exception.AuthMethodNotSupported, auth.controllers.AuthInfo.create, None, auth_data) def test_missing_auth_method_data(self): auth_data = {'methods': ['password']} auth_data = {'identity': auth_data} self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo.create, None, auth_data) def test_project_name_no_domain(self): auth_data = self.build_authentication_request( username='test', password='test', project_name='abc')['auth'] self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo.create, None, auth_data) def test_both_project_and_domain_in_scope(self): auth_data = self.build_authentication_request( user_id='test', password='test', project_name='test', domain_name='test')['auth'] self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo.create, None, auth_data) def test_get_method_names_duplicates(self): auth_data = self.build_authentication_request( token='test', user_id='test', password='test')['auth'] auth_data['identity']['methods'] = ['password', 'token', 'password', 'password'] context = None auth_info = auth.controllers.AuthInfo.create(context, auth_data) self.assertEqual(auth_info.get_method_names(), ['password', 'token']) def test_get_method_data_invalid_method(self): auth_data = self.build_authentication_request( user_id='test', password='test')['auth'] context = None auth_info = auth.controllers.AuthInfo.create(context, auth_data) method_name = uuid.uuid4().hex self.assertRaises(exception.ValidationError, auth_info.get_method_data, method_name) class TokenAPITests(object): # Why is this not just setUP? Because TokenAPITests is not a test class # itself. If TokenAPITests became a subclass of the testcase, it would get # called by the enumerate-tests-in-file code. The way the functions get # resolved in Python for multiple inheritance means that a setUp in this # would get skipped by the testrunner. def doSetUp(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_id=self.domain_id, password=self.user['password']) resp = self.post('/auth/tokens', body=auth_data) self.token_data = resp.result self.token = resp.headers.get('X-Subject-Token') self.headers = {'X-Subject-Token': resp.headers.get('X-Subject-Token')} def test_default_fixture_scope_token(self): self.assertIsNotNone(self.get_scoped_token()) def test_v3_token_id(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) resp = self.post('/auth/tokens', body=auth_data) token_data = resp.result token_id = resp.headers.get('X-Subject-Token') self.assertIn('expires_at', token_data['token']) expected_token_id = cms.cms_sign_token(json.dumps(token_data), CONF.signing.certfile, CONF.signing.keyfile) self.assertEqual(expected_token_id, token_id) # should be able to validate hash PKI token as well hash_token_id = cms.cms_hash_token(token_id) headers = {'X-Subject-Token': hash_token_id} resp = self.get('/auth/tokens', headers=headers) expected_token_data = resp.result self.assertDictEqual(expected_token_data, token_data) def test_v3_v2_intermix_non_default_domain_failed(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET', expected_status=401) def test_v3_v2_intermix_new_default_domain(self): # If the default_domain_id config option is changed, then should be # able to validate a v3 token with user in the new domain. # 1) Create a new domain for the user. new_domain_id = uuid.uuid4().hex new_domain = { 'description': uuid.uuid4().hex, 'enabled': True, 'id': new_domain_id, 'name': uuid.uuid4().hex, } self.assignment_api.create_domain(new_domain_id, new_domain) # 2) Create user in new domain. new_user_id = uuid.uuid4().hex new_user_password = uuid.uuid4().hex new_user = { 'id': new_user_id, 'name': uuid.uuid4().hex, 'domain_id': new_domain_id, 'password': new_user_password, 'email': uuid.uuid4().hex, } self.identity_api.create_user(new_user_id, new_user) # 3) Update the default_domain_id config option to the new domain self.config_fixture.config(group='identity', default_domain_id=new_domain_id) # 4) Get a token using v3 api. auth_data = self.build_authentication_request( user_id=new_user_id, password=new_user_password) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # 5) Authenticate token using v2 api. path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET') def test_v3_v2_intermix_domain_scoped_token_failed(self): # grant the domain role to user path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], domain_id=self.domain['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET', expected_status=401) def test_v3_v2_intermix_non_default_project_failed(self): auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.project['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET', expected_status=401) def test_v3_v2_unscoped_token_intermix(self): auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password']) resp = self.post('/auth/tokens', body=auth_data) token_data = resp.result token = resp.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET') v2_token = resp.result self.assertEqual(v2_token['access']['user']['id'], token_data['token']['user']['id']) # v2 token time has not fraction of second precision so # just need to make sure the non fraction part agrees self.assertIn(v2_token['access']['token']['expires'][:-1], token_data['token']['expires_at']) def test_v3_v2_token_intermix(self): # FIXME(gyee): PKI tokens are not interchangeable because token # data is baked into the token itself. auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.default_domain_project['id']) resp = self.post('/auth/tokens', body=auth_data) token_data = resp.result token = resp.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET') v2_token = resp.result self.assertEqual(v2_token['access']['user']['id'], token_data['token']['user']['id']) # v2 token time has not fraction of second precision so # just need to make sure the non fraction part agrees self.assertIn(v2_token['access']['token']['expires'][:-1], token_data['token']['expires_at']) self.assertEqual(v2_token['access']['user']['roles'][0]['id'], token_data['token']['roles'][0]['id']) def test_v3_v2_hashed_pki_token_intermix(self): auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.default_domain_project['id']) resp = self.post('/auth/tokens', body=auth_data) token_data = resp.result token = resp.headers.get('X-Subject-Token') # should be able to validate a hash PKI token in v2 too token = cms.cms_hash_token(token) path = '/v2.0/tokens/%s' % (token) resp = self.admin_request(path=path, token='ADMIN', method='GET') v2_token = resp.result self.assertEqual(v2_token['access']['user']['id'], token_data['token']['user']['id']) # v2 token time has not fraction of second precision so # just need to make sure the non fraction part agrees self.assertIn(v2_token['access']['token']['expires'][:-1], token_data['token']['expires_at']) self.assertEqual(v2_token['access']['user']['roles'][0]['id'], token_data['token']['roles'][0]['id']) def test_v2_v3_unscoped_token_intermix(self): body = { 'auth': { 'passwordCredentials': { 'userId': self.user['id'], 'password': self.user['password'] } }} resp = self.admin_request(path='/v2.0/tokens', method='POST', body=body) v2_token_data = resp.result v2_token = v2_token_data['access']['token']['id'] headers = {'X-Subject-Token': v2_token} resp = self.get('/auth/tokens', headers=headers) token_data = resp.result self.assertEqual(v2_token_data['access']['user']['id'], token_data['token']['user']['id']) # v2 token time has not fraction of second precision so # just need to make sure the non fraction part agrees self.assertIn(v2_token_data['access']['token']['expires'][-1], token_data['token']['expires_at']) def test_v2_v3_token_intermix(self): body = { 'auth': { 'passwordCredentials': { 'userId': self.user['id'], 'password': self.user['password'] }, 'tenantId': self.project['id'] }} resp = self.admin_request(path='/v2.0/tokens', method='POST', body=body) v2_token_data = resp.result v2_token = v2_token_data['access']['token']['id'] headers = {'X-Subject-Token': v2_token} resp = self.get('/auth/tokens', headers=headers) token_data = resp.result self.assertEqual(v2_token_data['access']['user']['id'], token_data['token']['user']['id']) # v2 token time has not fraction of second precision so # just need to make sure the non fraction part agrees self.assertIn(v2_token_data['access']['token']['expires'][-1], token_data['token']['expires_at']) self.assertEqual(v2_token_data['access']['user']['roles'][0]['name'], token_data['token']['roles'][0]['name']) def test_rescoping_token(self): expires = self.token_data['token']['expires_at'] auth_data = self.build_authentication_request( token=self.token, project_id=self.project_id) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) # make sure expires stayed the same self.assertEqual(expires, r.result['token']['expires_at']) def test_check_token(self): self.head('/auth/tokens', headers=self.headers, expected_status=204) def test_validate_token(self): r = self.get('/auth/tokens', headers=self.headers) self.assertValidUnscopedTokenResponse(r) def test_validate_token_nocatalog(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) resp = self.post('/auth/tokens', body=auth_data) headers = {'X-Subject-Token': resp.headers.get('X-Subject-Token')} r = self.get('/auth/tokens?nocatalog', headers=headers) self.assertValidProjectScopedTokenResponse(r, require_catalog=False) class TestPKITokenAPIs(test_v3.RestfulTestCase, TokenAPITests): def config_overrides(self): super(TestPKITokenAPIs, self).config_overrides() self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider') def setUp(self): super(TestPKITokenAPIs, self).setUp() self.doSetUp() class TestUUIDTokenAPIs(test_v3.RestfulTestCase, TokenAPITests): def config_overrides(self): super(TestUUIDTokenAPIs, self).config_overrides() self.config_fixture.config( group='token', provider='keystone.token.providers.uuid.Provider') def setUp(self): super(TestUUIDTokenAPIs, self).setUp() self.doSetUp() def test_v3_token_id(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) resp = self.post('/auth/tokens', body=auth_data) token_data = resp.result token_id = resp.headers.get('X-Subject-Token') self.assertIn('expires_at', token_data['token']) self.assertFalse(cms.is_ans1_token(token_id)) def test_v3_v2_hashed_pki_token_intermix(self): # this test is only applicable for PKI tokens # skipping it for UUID tokens pass class TestTokenRevokeSelfAndAdmin(test_v3.RestfulTestCase): """Test token revoke using v3 Identity API by token owner and admin.""" def setUp(self): """Setup for Test Cases. Two domains, domainA and domainB Two users in domainA, userNormalA and userAdminA One user in domainB, userAdminB """ super(TestTokenRevokeSelfAndAdmin, self).setUp() # DomainA setup self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.userAdminA = self.new_user_ref(domain_id=self.domainA['id']) self.userAdminA['password'] = uuid.uuid4().hex self.identity_api.create_user(self.userAdminA['id'], self.userAdminA) self.userNormalA = self.new_user_ref( domain_id=self.domainA['id']) self.userNormalA['password'] = uuid.uuid4().hex self.identity_api.create_user(self.userNormalA['id'], self.userNormalA) self.role1 = self.new_role_ref() self.role1['name'] = 'admin' self.assignment_api.create_role(self.role1['id'], self.role1) self.assignment_api.create_grant(self.role1['id'], user_id=self.userAdminA['id'], domain_id=self.domainA['id']) # Finally, switch to the v3 sample policy file self.orig_policy_file = CONF.policy_file from keystone.policy.backends import rules rules.reset() def config_overrides(self): super(TestTokenRevokeSelfAndAdmin, self).config_overrides() self.config_fixture.config( policy_file=tests.dirs.etc('policy.v3cloudsample.json')) def test_user_revokes_own_token(self): r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.userNormalA['id'], password=self.userNormalA['password'], user_domain_id=self.domainA['id'])) user_token = r.headers.get('X-Subject-Token') self.assertNotEmpty(user_token) headers = {'X-Subject-Token': user_token} r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.userAdminA['id'], password=self.userAdminA['password'], domain_name=self.domainA['name'])) adminA_token = r.headers.get('X-Subject-Token') self.head('/auth/tokens', headers=headers, expected_status=204, token=adminA_token) self.head('/auth/tokens', headers=headers, expected_status=204, token=user_token) self.delete('/auth/tokens', headers=headers, expected_status=204, token=user_token) # invalid X-Auth-Token and invalid X-Subject-Token (401) self.head('/auth/tokens', headers=headers, expected_status=401, token=user_token) # invalid X-Auth-Token and invalid X-Subject-Token (401) self.delete('/auth/tokens', headers=headers, expected_status=401, token=user_token) # valid X-Auth-Token and invalid X-Subject-Token (404) self.delete('/auth/tokens', headers=headers, expected_status=404, token=adminA_token) # valid X-Auth-Token and invalid X-Subject-Token (404) self.head('/auth/tokens', headers=headers, expected_status=404, token=adminA_token) def test_adminA_revokes_userA_token(self): r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.userNormalA['id'], password=self.userNormalA['password'], user_domain_id=self.domainA['id'])) user_token = r.headers.get('X-Subject-Token') self.assertNotEmpty(user_token) headers = {'X-Subject-Token': user_token} r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.userAdminA['id'], password=self.userAdminA['password'], domain_name=self.domainA['name'])) adminA_token = r.headers.get('X-Subject-Token') self.head('/auth/tokens', headers=headers, expected_status=204, token=adminA_token) self.head('/auth/tokens', headers=headers, expected_status=204, token=user_token) self.delete('/auth/tokens', headers=headers, expected_status=204, token=adminA_token) # invalid X-Auth-Token and invalid X-Subject-Token (401) self.head('/auth/tokens', headers=headers, expected_status=401, token=user_token) # valid X-Auth-Token and invalid X-Subject-Token (404) self.delete('/auth/tokens', headers=headers, expected_status=404, token=adminA_token) # valid X-Auth-Token and invalid X-Subject-Token (404) self.head('/auth/tokens', headers=headers, expected_status=404, token=adminA_token) def test_adminB_fails_revoking_userA_token(self): # DomainB setup self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.userAdminB = self.new_user_ref(domain_id=self.domainB['id']) self.userAdminB['password'] = uuid.uuid4().hex self.identity_api.create_user(self.userAdminB['id'], self.userAdminB) self.assignment_api.create_grant(self.role1['id'], user_id=self.userAdminB['id'], domain_id=self.domainB['id']) r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.userNormalA['id'], password=self.userNormalA['password'], user_domain_id=self.domainA['id'])) user_token = r.headers.get('X-Subject-Token') headers = {'X-Subject-Token': user_token} r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.userAdminB['id'], password=self.userAdminB['password'], domain_name=self.domainB['name'])) adminB_token = r.headers.get('X-Subject-Token') self.head('/auth/tokens', headers=headers, expected_status=403, token=adminB_token) self.delete('/auth/tokens', headers=headers, expected_status=403, token=adminB_token) @dependency.requires('revoke_api') class TestTokenRevokeById(test_v3.RestfulTestCase): """Test token revocation on the v3 Identity API.""" def config_overrides(self): super(TestTokenRevokeById, self).config_overrides() self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.kvs.Revoke') self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider', revoke_by_id=False) def setUp(self): """Setup for Token Revoking Test Cases. As well as the usual housekeeping, create a set of domains, users, groups, roles and projects for the subsequent tests: - Two domains: A & B - Three users (1, 2 and 3) - Three groups (1, 2 and 3) - Two roles (1 and 2) - DomainA owns user1, domainB owns user2 and user3 - DomainA owns group1 and group2, domainB owns group3 - User1 and user2 are members of group1 - User3 is a member of group2 - Two projects: A & B, both in domainA - Group1 has role1 on Project A and B, meaning that user1 and user2 will get these roles by virtue of membership - User1, 2 and 3 have role1 assigned to projectA - Group1 has role1 on Project A and B, meaning that user1 and user2 will get role1 (duplicated) by virtue of membership - User1 has role2 assigned to domainA """ super(TestTokenRevokeById, self).setUp() # Start by creating a couple of domains and projects self.domainA = self.new_domain_ref() self.assignment_api.create_domain(self.domainA['id'], self.domainA) self.domainB = self.new_domain_ref() self.assignment_api.create_domain(self.domainB['id'], self.domainB) self.projectA = self.new_project_ref(domain_id=self.domainA['id']) self.assignment_api.create_project(self.projectA['id'], self.projectA) self.projectB = self.new_project_ref(domain_id=self.domainA['id']) self.assignment_api.create_project(self.projectB['id'], self.projectB) # Now create some users self.user1 = self.new_user_ref( domain_id=self.domainA['id']) self.user1['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user1['id'], self.user1) self.user2 = self.new_user_ref( domain_id=self.domainB['id']) self.user2['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user2['id'], self.user2) self.user3 = self.new_user_ref( domain_id=self.domainB['id']) self.user3['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user3['id'], self.user3) self.group1 = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group1['id'], self.group1) self.group2 = self.new_group_ref( domain_id=self.domainA['id']) self.identity_api.create_group(self.group2['id'], self.group2) self.group3 = self.new_group_ref( domain_id=self.domainB['id']) self.identity_api.create_group(self.group3['id'], self.group3) self.identity_api.add_user_to_group(self.user1['id'], self.group1['id']) self.identity_api.add_user_to_group(self.user2['id'], self.group1['id']) self.identity_api.add_user_to_group(self.user3['id'], self.group2['id']) self.role1 = self.new_role_ref() self.assignment_api.create_role(self.role1['id'], self.role1) self.role2 = self.new_role_ref() self.assignment_api.create_role(self.role2['id'], self.role2) self.assignment_api.create_grant(self.role2['id'], user_id=self.user1['id'], domain_id=self.domainA['id']) self.assignment_api.create_grant(self.role1['id'], user_id=self.user1['id'], project_id=self.projectA['id']) self.assignment_api.create_grant(self.role1['id'], user_id=self.user2['id'], project_id=self.projectA['id']) self.assignment_api.create_grant(self.role1['id'], user_id=self.user3['id'], project_id=self.projectA['id']) self.assignment_api.create_grant(self.role1['id'], group_id=self.group1['id'], project_id=self.projectA['id']) def test_unscoped_token_remains_valid_after_role_assignment(self): r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'])) unscoped_token = r.headers.get('X-Subject-Token') r = self.post( '/auth/tokens', body=self.build_authentication_request( token=unscoped_token, project_id=self.projectA['id'])) scoped_token = r.headers.get('X-Subject-Token') # confirm both tokens are valid self.head('/auth/tokens', headers={'X-Subject-Token': unscoped_token}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': scoped_token}, expected_status=204) # create a new role role = self.new_role_ref() self.assignment_api.create_role(role['id'], role) # assign a new role self.put( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'project_id': self.projectA['id'], 'user_id': self.user1['id'], 'role_id': role['id']}) # both tokens should remain valid self.head('/auth/tokens', headers={'X-Subject-Token': unscoped_token}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': scoped_token}, expected_status=204) def test_deleting_user_grant_revokes_token(self): """Test deleting a user grant revokes token. Test Plan: - Get a token for user1, scoped to ProjectA - Delete the grant user1 has on ProjectA - Check token is no longer valid """ auth_data = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # Confirm token is valid self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) # Delete the grant, which should invalidate the token grant_url = ( '/projects/%(project_id)s/users/%(user_id)s/' 'roles/%(role_id)s' % { 'project_id': self.projectA['id'], 'user_id': self.user1['id'], 'role_id': self.role1['id']}) self.delete(grant_url) self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=404) def role_data_fixtures(self): self.projectC = self.new_project_ref(domain_id=self.domainA['id']) self.assignment_api.create_project(self.projectC['id'], self.projectC) self.user4 = self.new_user_ref(domain_id=self.domainB['id']) self.user4['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user4['id'], self.user4) self.user5 = self.new_user_ref( domain_id=self.domainA['id']) self.user5['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user5['id'], self.user5) self.user6 = self.new_user_ref( domain_id=self.domainA['id']) self.user6['password'] = uuid.uuid4().hex self.identity_api.create_user(self.user6['id'], self.user6) self.identity_api.add_user_to_group(self.user5['id'], self.group1['id']) self.assignment_api.create_grant(self.role1['id'], group_id=self.group1['id'], project_id=self.projectB['id']) self.assignment_api.create_grant(self.role2['id'], user_id=self.user4['id'], project_id=self.projectC['id']) self.assignment_api.create_grant(self.role1['id'], user_id=self.user6['id'], project_id=self.projectA['id']) self.assignment_api.create_grant(self.role1['id'], user_id=self.user6['id'], domain_id=self.domainA['id']) def test_deleting_role_revokes_token(self): """Test deleting a role revokes token. Add some additional test data, namely: - A third project (project C) - Three additional users - user4 owned by domainB and user5 and 6 owned by domainA (different domain ownership should not affect the test results, just provided to broaden test coverage) - User5 is a member of group1 - Group1 gets an additional assignment - role1 on projectB as well as its existing role1 on projectA - User4 has role2 on Project C - User6 has role1 on projectA and domainA - This allows us to create 5 tokens by virtue of different types of role assignment: - user1, scoped to ProjectA by virtue of user role1 assignment - user5, scoped to ProjectB by virtue of group role1 assignment - user4, scoped to ProjectC by virtue of user role2 assignment - user6, scoped to ProjectA by virtue of user role1 assignment - user6, scoped to DomainA by virtue of user role1 assignment - role1 is then deleted - Check the tokens on Project A and B, and DomainA are revoked, but not the one for Project C """ self.role_data_fixtures() # Now we are ready to start issuing requests auth_data = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) tokenA = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user5['id'], password=self.user5['password'], project_id=self.projectB['id']) resp = self.post('/auth/tokens', body=auth_data) tokenB = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user4['id'], password=self.user4['password'], project_id=self.projectC['id']) resp = self.post('/auth/tokens', body=auth_data) tokenC = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user6['id'], password=self.user6['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) tokenD = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user6['id'], password=self.user6['password'], domain_id=self.domainA['id']) resp = self.post('/auth/tokens', body=auth_data) tokenE = resp.headers.get('X-Subject-Token') # Confirm tokens are valid self.head('/auth/tokens', headers={'X-Subject-Token': tokenA}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': tokenB}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': tokenC}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': tokenD}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': tokenE}, expected_status=204) # Delete the role, which should invalidate the tokens role_url = '/roles/%s' % self.role1['id'] self.delete(role_url) # Check the tokens that used role1 is invalid self.head('/auth/tokens', headers={'X-Subject-Token': tokenA}, expected_status=404) self.head('/auth/tokens', headers={'X-Subject-Token': tokenB}, expected_status=404) self.head('/auth/tokens', headers={'X-Subject-Token': tokenD}, expected_status=404) self.head('/auth/tokens', headers={'X-Subject-Token': tokenE}, expected_status=404) # ...but the one using role2 is still valid self.head('/auth/tokens', headers={'X-Subject-Token': tokenC}, expected_status=204) def test_domain_user_role_assignment_maintains_token(self): """Test user-domain role assignment maintains existing token. Test Plan: - Get a token for user1, scoped to ProjectA - Create a grant for user1 on DomainB - Check token is still valid """ auth_data = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # Confirm token is valid self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) # Assign a role, which should not affect the token grant_url = ( '/domains/%(domain_id)s/users/%(user_id)s/' 'roles/%(role_id)s' % { 'domain_id': self.domainB['id'], 'user_id': self.user1['id'], 'role_id': self.role1['id']}) self.put(grant_url) self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) def test_disabling_project_revokes_token(self): resp = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id'])) token = resp.headers.get('X-Subject-Token') # confirm token is valid self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) # disable the project, which should invalidate the token self.patch( '/projects/%(project_id)s' % {'project_id': self.projectA['id']}, body={'project': {'enabled': False}}) # user should no longer have access to the project self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=404) resp = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id']), expected_status=401) def test_deleting_project_revokes_token(self): resp = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id'])) token = resp.headers.get('X-Subject-Token') # confirm token is valid self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) # delete the project, which should invalidate the token self.delete( '/projects/%(project_id)s' % {'project_id': self.projectA['id']}) # user should no longer have access to the project self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=404) resp = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id']), expected_status=401) def test_deleting_group_grant_revokes_tokens(self): """Test deleting a group grant revokes tokens. Test Plan: - Get a token for user1, scoped to ProjectA - Get a token for user2, scoped to ProjectA - Get a token for user3, scoped to ProjectA - Delete the grant group1 has on ProjectA - Check tokens for user1 & user2 are no longer valid, since user1 and user2 are members of group1 - Check token for user3 is still valid """ auth_data = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token1 = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user2['id'], password=self.user2['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token2 = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token3 = resp.headers.get('X-Subject-Token') # Confirm tokens are valid self.head('/auth/tokens', headers={'X-Subject-Token': token1}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': token2}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': token3}, expected_status=204) # Delete the group grant, which should invalidate the # tokens for user1 and user2 grant_url = ( '/projects/%(project_id)s/groups/%(group_id)s/' 'roles/%(role_id)s' % { 'project_id': self.projectA['id'], 'group_id': self.group1['id'], 'role_id': self.role1['id']}) self.delete(grant_url) self.head('/auth/tokens', headers={'X-Subject-Token': token1}, expected_status=404) self.head('/auth/tokens', headers={'X-Subject-Token': token2}, expected_status=404) # But user3's token should still be valid self.head('/auth/tokens', headers={'X-Subject-Token': token3}, expected_status=204) def test_domain_group_role_assignment_maintains_token(self): """Test domain-group role assignment maintains existing token. Test Plan: - Get a token for user1, scoped to ProjectA - Create a grant for group1 on DomainB - Check token is still longer valid """ auth_data = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') # Confirm token is valid self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) # Delete the grant, which should invalidate the token grant_url = ( '/domains/%(domain_id)s/groups/%(group_id)s/' 'roles/%(role_id)s' % { 'domain_id': self.domainB['id'], 'group_id': self.group1['id'], 'role_id': self.role1['id']}) self.put(grant_url) self.head('/auth/tokens', headers={'X-Subject-Token': token}, expected_status=204) def test_group_membership_changes_revokes_token(self): """Test add/removal to/from group revokes token. Test Plan: - Get a token for user1, scoped to ProjectA - Get a token for user2, scoped to ProjectA - Remove user1 from group1 - Check token for user1 is no longer valid - Check token for user2 is still valid, even though user2 is also part of group1 - Add user2 to group2 - Check token for user2 is now no longer valid """ auth_data = self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token1 = resp.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( user_id=self.user2['id'], password=self.user2['password'], project_id=self.projectA['id']) resp = self.post('/auth/tokens', body=auth_data) token2 = resp.headers.get('X-Subject-Token') # Confirm tokens are valid self.head('/auth/tokens', headers={'X-Subject-Token': token1}, expected_status=204) self.head('/auth/tokens', headers={'X-Subject-Token': token2}, expected_status=204) # Remove user1 from group1, which should invalidate # the token self.delete('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group1['id'], 'user_id': self.user1['id']}) self.head('/auth/tokens', headers={'X-Subject-Token': token1}, expected_status=404) # But user2's token should still be valid self.head('/auth/tokens', headers={'X-Subject-Token': token2}, expected_status=204) # Adding user2 to a group should not invalidate token self.put('/groups/%(group_id)s/users/%(user_id)s' % { 'group_id': self.group2['id'], 'user_id': self.user2['id']}) self.head('/auth/tokens', headers={'X-Subject-Token': token2}, expected_status=204) def test_removing_role_assignment_does_not_affect_other_users(self): """Revoking a role from one user should not affect other users.""" r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id'])) user1_token = r.headers.get('X-Subject-Token') r = self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id'])) user3_token = r.headers.get('X-Subject-Token') # delete relationships between user1 and projectA from setUp self.delete( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'project_id': self.projectA['id'], 'user_id': self.user1['id'], 'role_id': self.role1['id']}) self.delete( '/projects/%(project_id)s/groups/%(group_id)s/roles/%(role_id)s' % {'project_id': self.projectA['id'], 'group_id': self.group1['id'], 'role_id': self.role1['id']}) # authorization for the first user should now fail self.head('/auth/tokens', headers={'X-Subject-Token': user1_token}, expected_status=404) self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user1['id'], password=self.user1['password'], project_id=self.projectA['id']), expected_status=401) # authorization for the second user should still succeed self.head('/auth/tokens', headers={'X-Subject-Token': user3_token}, expected_status=204) self.post( '/auth/tokens', body=self.build_authentication_request( user_id=self.user3['id'], password=self.user3['password'], project_id=self.projectA['id'])) def test_deleting_project_deletes_grants(self): # This is to make it a little bit more pretty with PEP8 role_path = ('/projects/%(project_id)s/users/%(user_id)s/' 'roles/%(role_id)s') role_path = role_path % {'user_id': self.user['id'], 'project_id': self.projectA['id'], 'role_id': self.role['id']} # grant the user a role on the project self.put(role_path) # delete the project, which should remove the roles self.delete( '/projects/%(project_id)s' % {'project_id': self.projectA['id']}) # Make sure that we get a NotFound(404) when heading that role. self.head(role_path, expected_status=404) @dependency.requires('revoke_api') class TestTokenRevokeApi(TestTokenRevokeById): EXTENSION_NAME = 'revoke' EXTENSION_TO_ADD = 'revoke_extension' """Test token revocation on the v3 Identity API.""" def config_overrides(self): super(TestTokenRevokeApi, self).config_overrides() self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.kvs.Revoke') self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider', revoke_by_id=False) def assertValidDeletedProjectResponse(self, events_response, project_id): events = events_response['events'] self.assertEqual(1, len(events)) self.assertEqual(project_id, events[0]['project_id']) self.assertIsNotNone(events[0]['issued_before']) self.assertIsNotNone(events_response['links']) del (events_response['events'][0]['issued_before']) del (events_response['links']) expected_response = {'events': [{'project_id': project_id}]} self.assertEqual(expected_response, events_response) def assertDomainInList(self, events_response, domain_id): events = events_response['events'] self.assertEqual(1, len(events)) self.assertEqual(domain_id, events[0]['domain_id']) self.assertIsNotNone(events[0]['issued_before']) self.assertIsNotNone(events_response['links']) del (events_response['events'][0]['issued_before']) del (events_response['links']) expected_response = {'events': [{'domain_id': domain_id}]} self.assertEqual(expected_response, events_response) def assertValidRevokedTokenResponse(self, events_response, user_id): events = events_response['events'] self.assertEqual(1, len(events)) self.assertEqual(user_id, events[0]['user_id']) self.assertIsNotNone(events[0]['expires_at']) self.assertIsNotNone(events[0]['issued_before']) self.assertIsNotNone(events_response['links']) del (events_response['events'][0]['expires_at']) del (events_response['events'][0]['issued_before']) del (events_response['links']) expected_response = {'events': [{'user_id': user_id}]} self.assertEqual(expected_response, events_response) def test_revoke_token(self): scoped_token = self.get_scoped_token() headers = {'X-Subject-Token': scoped_token} self.head('/auth/tokens', headers=headers, expected_status=204) self.delete('/auth/tokens', headers=headers, expected_status=204) self.head('/auth/tokens', headers=headers, expected_status=404) events_response = self.get('/OS-REVOKE/events', expected_status=200).json_body self.assertValidRevokedTokenResponse(events_response, self.user['id']) def get_v2_token(self): body = { 'auth': { 'passwordCredentials': { 'username': self.default_domain_user['name'], 'password': self.default_domain_user['password'], }, }, } r = self.admin_request(method='POST', path='/v2.0/tokens', body=body) return r.json_body['access']['token']['id'] def test_revoke_v2_token(self): token = self.get_v2_token() headers = {'X-Subject-Token': token} self.head('/auth/tokens', headers=headers, expected_status=204) self.delete('/auth/tokens', headers=headers, expected_status=204) self.head('/auth/tokens', headers=headers, expected_status=404) events_response = self.get('/OS-REVOKE/events', expected_status=200).json_body self.assertValidRevokedTokenResponse(events_response, self.default_domain_user['id']) def test_revoke_by_id_false_410(self): self.get('/auth/tokens/OS-PKI/revoked', expected_status=410) def test_list_delete_project_shows_in_event_list(self): self.role_data_fixtures() events = self.get('/OS-REVOKE/events', expected_status=200).json_body['events'] self.assertEqual([], events) self.delete( '/projects/%(project_id)s' % {'project_id': self.projectA['id']}) events_response = self.get('/OS-REVOKE/events', expected_status=200).json_body self.assertValidDeletedProjectResponse(events_response, self.projectA['id']) def test_disable_domain_shows_in_event_list(self): events = self.get('/OS-REVOKE/events', expected_status=200).json_body['events'] self.assertEqual([], events) disable_body = {'domain': {'enabled': False}} self.patch( '/domains/%(project_id)s' % {'project_id': self.domainA['id']}, body=disable_body) events = self.get('/OS-REVOKE/events', expected_status=200).json_body self.assertDomainInList(events, self.domainA['id']) def assertUserAndExpiryInList(self, events, user_id, expires_at): found = False for e in events: if e['user_id'] == user_id and e['expires_at'] == expires_at: found = True self.assertTrue(found, 'event with correct user_id %s and expires_at value ' 'not in list' % user_id) def test_list_delete_token_shows_in_event_list(self): self.role_data_fixtures() events = self.get('/OS-REVOKE/events', expected_status=200).json_body['events'] self.assertEqual([], events) scoped_token = self.get_scoped_token() headers = {'X-Subject-Token': scoped_token} auth_req = self.build_authentication_request(token=scoped_token) response = self.post('/auth/tokens', body=auth_req) token2 = response.json_body['token'] headers2 = {'X-Subject-Token': response.headers['X-Subject-Token']} response = self.post('/auth/tokens', body=auth_req) response.json_body['token'] headers3 = {'X-Subject-Token': response.headers['X-Subject-Token']} scoped_token = self.get_scoped_token() headers_unrevoked = {'X-Subject-Token': scoped_token} self.head('/auth/tokens', headers=headers, expected_status=204) self.head('/auth/tokens', headers=headers2, expected_status=204) self.head('/auth/tokens', headers=headers3, expected_status=204) self.head('/auth/tokens', headers=headers_unrevoked, expected_status=204) self.delete('/auth/tokens', headers=headers, expected_status=204) # NOTE(ayoung): not deleting token3, as it should be deleted # by previous events_response = self.get('/OS-REVOKE/events', expected_status=200).json_body events = events_response['events'] self.assertEqual(1, len(events)) self.assertUserAndExpiryInList(events, token2['user']['id'], token2['expires_at']) self.assertValidRevokedTokenResponse(events_response, self.user['id']) self.head('/auth/tokens', headers=headers, expected_status=404) self.head('/auth/tokens', headers=headers2, expected_status=404) self.head('/auth/tokens', headers=headers3, expected_status=404) self.head('/auth/tokens', headers=headers_unrevoked, expected_status=204) def test_list_with_filter(self): self.role_data_fixtures() events = self.get('/OS-REVOKE/events', expected_status=200).json_body['events'] self.assertEqual(0, len(events)) scoped_token = self.get_scoped_token() headers = {'X-Subject-Token': scoped_token} auth = self.build_authentication_request(token=scoped_token) response = self.post('/auth/tokens', body=auth) headers2 = {'X-Subject-Token': response.headers['X-Subject-Token']} self.delete('/auth/tokens', headers=headers, expected_status=204) self.delete('/auth/tokens', headers=headers2, expected_status=204) events = self.get('/OS-REVOKE/events', expected_status=200).json_body['events'] self.assertEqual(2, len(events)) future = timeutils.isotime(timeutils.utcnow() + datetime.timedelta(seconds=1000)) events = self.get('/OS-REVOKE/events?since=%s' % (future), expected_status=200).json_body['events'] self.assertEqual(0, len(events)) class TestAuthExternalDisabled(test_v3.RestfulTestCase): def config_overrides(self): super(TestAuthExternalDisabled, self).config_overrides() self.config_fixture.config( group='auth', methods=['keystone.auth.plugins.password.Password', 'keystone.auth.plugins.token.Token']) def test_remote_user_disabled(self): api = auth.controllers.Auth() remote_user = '%s@%s' % (self.user['name'], self.domain['name']) context, auth_info, auth_context = self.build_external_auth_request( remote_user) self.assertRaises(exception.Unauthorized, api.authenticate, context, auth_info, auth_context) class TestAuthExternalLegacyDefaultDomain(test_v3.RestfulTestCase): content_type = 'json' def config_overrides(self): super(TestAuthExternalLegacyDefaultDomain, self).config_overrides() self.config_fixture.config( group='auth', methods=['keystone.auth.plugins.external.LegacyDefaultDomain', 'keystone.auth.plugins.password.Password', 'keystone.auth.plugins.token.Token']) def test_remote_user_no_realm(self): CONF.auth.methods = 'external' api = auth.controllers.Auth() context, auth_info, auth_context = self.build_external_auth_request( self.default_domain_user['name']) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.default_domain_user['id']) def test_remote_user_no_domain(self): api = auth.controllers.Auth() context, auth_info, auth_context = self.build_external_auth_request( self.user['name']) self.assertRaises(exception.Unauthorized, api.authenticate, context, auth_info, auth_context) class TestAuthExternalLegacyDomain(test_v3.RestfulTestCase): content_type = 'json' def config_overrides(self): super(TestAuthExternalLegacyDomain, self).config_overrides() self.config_fixture.config( group='auth', methods=['keystone.auth.plugins.external.LegacyDomain', 'keystone.auth.plugins.password.Password', 'keystone.auth.plugins.token.Token']) def test_remote_user_with_realm(self): api = auth.controllers.Auth() remote_user = '%s@%s' % (self.user['name'], self.domain['name']) context, auth_info, auth_context = self.build_external_auth_request( remote_user) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.user['id']) # Now test to make sure the user name can, itself, contain the # '@' character. user = {'name': 'myname@mydivision'} self.identity_api.update_user(self.user['id'], user) remote_user = '%s@%s' % (user['name'], self.domain['name']) context, auth_info, auth_context = self.build_external_auth_request( remote_user) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.user['id']) def test_project_id_scoped_with_remote_user(self): CONF.token.bind = ['kerberos'] auth_data = self.build_authentication_request( project_id=self.project['id']) remote_user = '%s@%s' % (self.user['name'], self.domain['name']) self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'AUTH_TYPE': 'Negotiate'}) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidProjectScopedTokenResponse(r) self.assertEqual(token['bind']['kerberos'], self.user['name']) def test_unscoped_bind_with_remote_user(self): CONF.token.bind = ['kerberos'] auth_data = self.build_authentication_request() remote_user = '%s@%s' % (self.user['name'], self.domain['name']) self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'AUTH_TYPE': 'Negotiate'}) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidUnscopedTokenResponse(r) self.assertEqual(token['bind']['kerberos'], self.user['name']) class TestAuthExternalDomain(test_v3.RestfulTestCase): content_type = 'json' def config_overrides(self): super(TestAuthExternalDomain, self).config_overrides() self.config_fixture.config( group='auth', methods=['keystone.auth.plugins.external.Domain', 'keystone.auth.plugins.password.Password', 'keystone.auth.plugins.token.Token']) def test_remote_user_with_realm(self): api = auth.controllers.Auth() remote_user = self.user['name'] remote_domain = self.domain['name'] context, auth_info, auth_context = self.build_external_auth_request( remote_user, remote_domain=remote_domain) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.user['id']) # Now test to make sure the user name can, itself, contain the # '@' character. user = {'name': 'myname@mydivision'} self.identity_api.update_user(self.user['id'], user) remote_user = user['name'] context, auth_info, auth_context = self.build_external_auth_request( remote_user, remote_domain=remote_domain) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.user['id']) def test_project_id_scoped_with_remote_user(self): CONF.token.bind = ['kerberos'] auth_data = self.build_authentication_request( project_id=self.project['id']) remote_user = self.user['name'] remote_domain = self.domain['name'] self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'REMOTE_DOMAIN': remote_domain, 'AUTH_TYPE': 'Negotiate'}) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidProjectScopedTokenResponse(r) self.assertEqual(token['bind']['kerberos'], self.user['name']) def test_unscoped_bind_with_remote_user(self): CONF.token.bind = ['kerberos'] auth_data = self.build_authentication_request() remote_user = self.user['name'] remote_domain = self.domain['name'] self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'REMOTE_DOMAIN': remote_domain, 'AUTH_TYPE': 'Negotiate'}) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidUnscopedTokenResponse(r) self.assertEqual(token['bind']['kerberos'], self.user['name']) class TestAuthJSON(test_v3.RestfulTestCase): content_type = 'json' def test_unscoped_token_with_user_id(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def test_unscoped_token_with_user_domain_id(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_id=self.domain['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def test_unscoped_token_with_user_domain_name(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_name=self.domain['name'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def test_project_id_scoped_token_with_user_id(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) def test_default_project_id_scoped_token_with_user_id(self): # create a second project to work with ref = self.new_project_ref(domain_id=self.domain_id) r = self.post('/projects', body={'project': ref}) project = self.assertValidProjectResponse(r, ref) # grant the user a role on the project self.put( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'user_id': self.user['id'], 'project_id': project['id'], 'role_id': self.role['id']}) # set the user's preferred project body = {'user': {'default_project_id': project['id']}} r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body=body) self.assertValidUserResponse(r) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) self.assertEqual(r.result['token']['project']['id'], project['id']) def test_default_project_id_scoped_token_with_user_id_no_catalog(self): # create a second project to work with ref = self.new_project_ref(domain_id=self.domain_id) r = self.post('/projects', body={'project': ref}) project = self.assertValidProjectResponse(r, ref) # grant the user a role on the project self.put( '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { 'user_id': self.user['id'], 'project_id': project['id'], 'role_id': self.role['id']}) # set the user's preferred project body = {'user': {'default_project_id': project['id']}} r = self.patch('/users/%(user_id)s' % { 'user_id': self.user['id']}, body=body) self.assertValidUserResponse(r) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens?nocatalog', body=auth_data) self.assertValidProjectScopedTokenResponse(r, require_catalog=False) self.assertEqual(r.result['token']['project']['id'], project['id']) def test_implicit_project_id_scoped_token_with_user_id_no_catalog(self): # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens?nocatalog', body=auth_data) self.assertValidProjectScopedTokenResponse(r, require_catalog=False) self.assertEqual(r.result['token']['project']['id'], self.project['id']) def _check_disabled_endpoint_result(self, catalog, disabled_endpoint_id): endpoints = catalog[0]['endpoints'] endpoint_ids = [ep['id'] for ep in endpoints] self.assertEqual([self.endpoint_id], endpoint_ids) def test_auth_catalog_disabled_service(self): """On authenticate, get a catalog that excludes disabled services.""" # although the child endpoint is enabled, the service is disabled self.assertTrue(self.endpoint['enabled']) self.catalog_api.update_service( self.endpoint['service_id'], {'enabled': False}) service = self.catalog_api.get_service(self.endpoint['service_id']) self.assertFalse(service['enabled']) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) # In JSON, this is an empty list. In XML, this is an empty string. self.assertFalse(r.result['token']['catalog']) def test_auth_catalog_disabled_endpoint(self): """On authenticate, get a catalog that excludes disabled endpoints.""" # Create a disabled endpoint that's like the enabled one. disabled_endpoint_ref = copy.copy(self.endpoint) disabled_endpoint_id = uuid.uuid4().hex disabled_endpoint_ref.update({ 'id': disabled_endpoint_id, 'enabled': False, 'interface': 'internal' }) self.catalog_api.create_endpoint(disabled_endpoint_id, disabled_endpoint_ref) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) self._check_disabled_endpoint_result(r.result['token']['catalog'], disabled_endpoint_id) def test_project_id_scoped_token_with_user_id_401(self): project_id = uuid.uuid4().hex project = self.new_project_ref(domain_id=self.domain_id) self.assignment_api.create_project(project_id, project) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], project_id=project['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_user_and_group_roles_scoped_token(self): """Test correct roles are returned in scoped token. Test Plan: - Create a domain, with 1 project, 2 users (user1 and user2) and 2 groups (group1 and group2) - Make user1 a member of group1, user2 a member of group2 - Create 8 roles, assigning them to each of the 8 combinations of users/groups on domain/project - Get a project scoped token for user1, checking that the right two roles are returned (one directly assigned, one by virtue of group membership) - Repeat this for a domain scoped token - Make user1 also a member of group2 - Get another scoped token making sure the additional role shows up - User2 is just here as a spoiler, to make sure we don't get any roles uniquely assigned to it returned in any of our tokens """ domainA = self.new_domain_ref() self.assignment_api.create_domain(domainA['id'], domainA) projectA = self.new_project_ref(domain_id=domainA['id']) self.assignment_api.create_project(projectA['id'], projectA) user1 = self.new_user_ref( domain_id=domainA['id']) user1['password'] = uuid.uuid4().hex self.identity_api.create_user(user1['id'], user1) user2 = self.new_user_ref( domain_id=domainA['id']) user2['password'] = uuid.uuid4().hex self.identity_api.create_user(user2['id'], user2) group1 = self.new_group_ref( domain_id=domainA['id']) self.identity_api.create_group(group1['id'], group1) group2 = self.new_group_ref( domain_id=domainA['id']) self.identity_api.create_group(group2['id'], group2) self.identity_api.add_user_to_group(user1['id'], group1['id']) self.identity_api.add_user_to_group(user2['id'], group2['id']) # Now create all the roles and assign them role_list = [] for _ in range(8): role = self.new_role_ref() self.assignment_api.create_role(role['id'], role) role_list.append(role) self.assignment_api.create_grant(role_list[0]['id'], user_id=user1['id'], domain_id=domainA['id']) self.assignment_api.create_grant(role_list[1]['id'], user_id=user1['id'], project_id=projectA['id']) self.assignment_api.create_grant(role_list[2]['id'], user_id=user2['id'], domain_id=domainA['id']) self.assignment_api.create_grant(role_list[3]['id'], user_id=user2['id'], project_id=projectA['id']) self.assignment_api.create_grant(role_list[4]['id'], group_id=group1['id'], domain_id=domainA['id']) self.assignment_api.create_grant(role_list[5]['id'], group_id=group1['id'], project_id=projectA['id']) self.assignment_api.create_grant(role_list[6]['id'], group_id=group2['id'], domain_id=domainA['id']) self.assignment_api.create_grant(role_list[7]['id'], group_id=group2['id'], project_id=projectA['id']) # First, get a project scoped token - which should # contain the direct user role and the one by virtue # of group membership auth_data = self.build_authentication_request( user_id=user1['id'], password=user1['password'], project_id=projectA['id']) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidScopedTokenResponse(r) roles_ids = [] for ref in token['roles']: roles_ids.append(ref['id']) self.assertEqual(2, len(token['roles'])) self.assertIn(role_list[1]['id'], roles_ids) self.assertIn(role_list[5]['id'], roles_ids) # Now the same thing for a domain scoped token auth_data = self.build_authentication_request( user_id=user1['id'], password=user1['password'], domain_id=domainA['id']) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidScopedTokenResponse(r) roles_ids = [] for ref in token['roles']: roles_ids.append(ref['id']) self.assertEqual(2, len(token['roles'])) self.assertIn(role_list[0]['id'], roles_ids) self.assertIn(role_list[4]['id'], roles_ids) # Finally, add user1 to the 2nd group, and get a new # scoped token - the extra role should now be included # by virtue of the 2nd group self.identity_api.add_user_to_group(user1['id'], group2['id']) auth_data = self.build_authentication_request( user_id=user1['id'], password=user1['password'], project_id=projectA['id']) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidScopedTokenResponse(r) roles_ids = [] for ref in token['roles']: roles_ids.append(ref['id']) self.assertEqual(3, len(token['roles'])) self.assertIn(role_list[1]['id'], roles_ids) self.assertIn(role_list[5]['id'], roles_ids) self.assertIn(role_list[7]['id'], roles_ids) def test_project_id_scoped_token_with_user_domain_id(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_id=self.domain['id'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) def test_project_id_scoped_token_with_user_domain_name(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_name=self.domain['name'], password=self.user['password'], project_id=self.project['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) def test_domain_id_scoped_token_with_user_id(self): path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], domain_id=self.domain['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_id_scoped_token_with_user_domain_id(self): path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( username=self.user['name'], user_domain_id=self.domain['id'], password=self.user['password'], domain_id=self.domain['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_id_scoped_token_with_user_domain_name(self): path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( username=self.user['name'], user_domain_name=self.domain['name'], password=self.user['password'], domain_id=self.domain['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_name_scoped_token_with_user_id(self): path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], domain_name=self.domain['name']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_name_scoped_token_with_user_domain_id(self): path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( username=self.user['name'], user_domain_id=self.domain['id'], password=self.user['password'], domain_name=self.domain['name']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_name_scoped_token_with_user_domain_name(self): path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) auth_data = self.build_authentication_request( username=self.user['name'], user_domain_name=self.domain['name'], password=self.user['password'], domain_name=self.domain['name']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_scope_token_with_group_role(self): group_id = uuid.uuid4().hex group = self.new_group_ref( domain_id=self.domain_id) group['id'] = group_id self.identity_api.create_group(group_id, group) # add user to group self.identity_api.add_user_to_group(self.user['id'], group['id']) # grant the domain role to group path = '/domains/%s/groups/%s/roles/%s' % ( self.domain['id'], group['id'], self.role['id']) self.put(path=path) # now get a domain-scoped token auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], domain_id=self.domain['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_scope_token_with_name(self): # grant the domain role to user path = '/domains/%s/users/%s/roles/%s' % ( self.domain['id'], self.user['id'], self.role['id']) self.put(path=path) # now get a domain-scoped token auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], domain_name=self.domain['name']) r = self.post('/auth/tokens', body=auth_data) self.assertValidDomainScopedTokenResponse(r) def test_domain_scope_failed(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], domain_id=self.domain['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_auth_with_id(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) token = r.headers.get('X-Subject-Token') # test token auth auth_data = self.build_authentication_request(token=token) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def get_v2_token(self, tenant_id=None): body = { 'auth': { 'passwordCredentials': { 'username': self.default_domain_user['name'], 'password': self.default_domain_user['password'], }, }, } r = self.admin_request(method='POST', path='/v2.0/tokens', body=body) return r def test_validate_v2_unscoped_token_with_v3_api(self): v2_token = self.get_v2_token().result['access']['token']['id'] auth_data = self.build_authentication_request(token=v2_token) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def test_validate_v2_scoped_token_with_v3_api(self): v2_response = self.get_v2_token( tenant_id=self.default_domain_project['id']) result = v2_response.result v2_token = result['access']['token']['id'] auth_data = self.build_authentication_request( token=v2_token, project_id=self.default_domain_project['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidScopedTokenResponse(r) def test_invalid_user_id(self): auth_data = self.build_authentication_request( user_id=uuid.uuid4().hex, password=self.user['password']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_invalid_user_name(self): auth_data = self.build_authentication_request( username=uuid.uuid4().hex, user_domain_id=self.domain['id'], password=self.user['password']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_invalid_domain_id(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_id=uuid.uuid4().hex, password=self.user['password']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_invalid_domain_name(self): auth_data = self.build_authentication_request( username=self.user['name'], user_domain_name=uuid.uuid4().hex, password=self.user['password']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_invalid_password(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=uuid.uuid4().hex) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_remote_user_no_realm(self): CONF.auth.methods = 'external' api = auth.controllers.Auth() context, auth_info, auth_context = self.build_external_auth_request( self.default_domain_user['name']) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.default_domain_user['id']) # Now test to make sure the user name can, itself, contain the # '@' character. user = {'name': 'myname@mydivision'} self.identity_api.update_user(self.default_domain_user['id'], user) context, auth_info, auth_context = self.build_external_auth_request( user["name"]) api.authenticate(context, auth_info, auth_context) self.assertEqual(auth_context['user_id'], self.default_domain_user['id']) def test_remote_user_no_domain(self): api = auth.controllers.Auth() context, auth_info, auth_context = self.build_external_auth_request( self.user['name']) self.assertRaises(exception.Unauthorized, api.authenticate, context, auth_info, auth_context) def test_remote_user_and_password(self): #both REMOTE_USER and password methods must pass. #note that they do not have to match api = auth.controllers.Auth() auth_data = self.build_authentication_request( user_domain_id=self.domain['id'], username=self.user['name'], password=self.user['password'])['auth'] context, auth_info, auth_context = self.build_external_auth_request( self.default_domain_user['name'], auth_data=auth_data) api.authenticate(context, auth_info, auth_context) def test_remote_user_and_explicit_external(self): #both REMOTE_USER and password methods must pass. #note that they do not have to match auth_data = self.build_authentication_request( user_domain_id=self.domain['id'], username=self.user['name'], password=self.user['password'])['auth'] auth_data['identity']['methods'] = ["password", "external"] auth_data['identity']['external'] = {} api = auth.controllers.Auth() auth_info = auth.controllers.AuthInfo(None, auth_data) auth_context = {'extras': {}, 'method_names': []} self.assertRaises(exception.Unauthorized, api.authenticate, self.empty_context, auth_info, auth_context) def test_remote_user_bad_password(self): #both REMOTE_USER and password methods must pass. api = auth.controllers.Auth() auth_data = self.build_authentication_request( user_domain_id=self.domain['id'], username=self.user['name'], password='badpassword')['auth'] context, auth_info, auth_context = self.build_external_auth_request( self.default_domain_user['name'], auth_data=auth_data) self.assertRaises(exception.Unauthorized, api.authenticate, context, auth_info, auth_context) def test_bind_not_set_with_remote_user(self): CONF.token.bind = [] auth_data = self.build_authentication_request() remote_user = self.default_domain_user['name'] self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'AUTH_TYPE': 'Negotiate'}) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidUnscopedTokenResponse(r) self.assertNotIn('bind', token) #TODO(ayoung): move to TestPKITokenAPIs; it will be run for both formats def test_verify_with_bound_token(self): self.config_fixture.config(group='token', bind='kerberos') auth_data = self.build_authentication_request( project_id=self.project['id']) remote_user = self.default_domain_user['name'] self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'AUTH_TYPE': 'Negotiate'}) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') headers = {'X-Subject-Token': token} r = self.get('/auth/tokens', headers=headers, token=token) token = self.assertValidProjectScopedTokenResponse(r) self.assertEqual(token['bind']['kerberos'], self.default_domain_user['name']) def test_auth_with_bind_token(self): CONF.token.bind = ['kerberos'] auth_data = self.build_authentication_request() remote_user = self.default_domain_user['name'] self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'AUTH_TYPE': 'Negotiate'}) r = self.post('/auth/tokens', body=auth_data) # the unscoped token should have bind information in it token = self.assertValidUnscopedTokenResponse(r) self.assertEqual(token['bind']['kerberos'], remote_user) token = r.headers.get('X-Subject-Token') # using unscoped token with remote user succeeds auth_params = {'token': token, 'project_id': self.project_id} auth_data = self.build_authentication_request(**auth_params) r = self.post('/auth/tokens', body=auth_data) token = self.assertValidProjectScopedTokenResponse(r) # the bind information should be carried over from the original token self.assertEqual(token['bind']['kerberos'], remote_user) def test_v2_v3_bind_token_intermix(self): self.config_fixture.config(group='token', bind='kerberos') # we need our own user registered to the default domain because of # the way external auth works. remote_user = self.default_domain_user['name'] self.admin_app.extra_environ.update({'REMOTE_USER': remote_user, 'AUTH_TYPE': 'Negotiate'}) body = {'auth': {}} resp = self.admin_request(path='/v2.0/tokens', method='POST', body=body) v2_token_data = resp.result bind = v2_token_data['access']['token']['bind'] self.assertEqual(bind['kerberos'], self.default_domain_user['name']) v2_token_id = v2_token_data['access']['token']['id'] headers = {'X-Subject-Token': v2_token_id} resp = self.get('/auth/tokens', headers=headers) token_data = resp.result self.assertDictEqual(v2_token_data['access']['token']['bind'], token_data['token']['bind']) def test_authenticating_a_user_with_no_password(self): user = self.new_user_ref(domain_id=self.domain['id']) user.pop('password', None) # can't have a password for this test self.identity_api.create_user(user['id'], user) auth_data = self.build_authentication_request( user_id=user['id'], password='password') self.post('/auth/tokens', body=auth_data, expected_status=401) def test_disabled_default_project_result_in_unscoped_token(self): # create a disabled project to work with project = self.create_new_default_project_for_user( self.user['id'], self.domain_id, enable_project=False) # assign a role to user for the new project self.assignment_api.add_role_to_user_and_project(self.user['id'], project['id'], self.role_id) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def test_disabled_default_project_domain_result_in_unscoped_token(self): domain_ref = self.new_domain_ref() r = self.post('/domains', body={'domain': domain_ref}) domain = self.assertValidDomainResponse(r, domain_ref) project = self.create_new_default_project_for_user( self.user['id'], domain['id']) # assign a role to user for the new project self.assignment_api.add_role_to_user_and_project(self.user['id'], project['id'], self.role_id) # now disable the project domain body = {'domain': {'enabled': False}} r = self.patch('/domains/%(domain_id)s' % {'domain_id': domain['id']}, body=body) self.assertValidDomainResponse(r) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) def test_no_access_to_default_project_result_in_unscoped_token(self): # create a disabled project to work with self.create_new_default_project_for_user(self.user['id'], self.domain_id) # attempt to authenticate without requesting a project auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password']) r = self.post('/auth/tokens', body=auth_data) self.assertValidUnscopedTokenResponse(r) class TestAuthXML(TestAuthJSON): content_type = 'xml' def _check_disabled_endpoint_result(self, catalog, disabled_endpoint_id): # FIXME(blk-u): As far as I can tell the catalog in the XML result is # broken. Looks like it includes only one endpoint or the other, and # which one is included is random. endpoint = catalog['service']['endpoint'] self.assertEqual(self.endpoint_id, endpoint['id']) class TestTrustOptional(test_v3.RestfulTestCase): def config_overrides(self): super(TestTrustOptional, self).config_overrides() self.config_fixture.config(group='trust', enabled=False) def test_trusts_404(self): self.get('/OS-TRUST/trusts', body={'trust': {}}, expected_status=404) self.post('/OS-TRUST/trusts', body={'trust': {}}, expected_status=404) def test_auth_with_scope_in_trust_403(self): auth_data = self.build_authentication_request( user_id=self.user['id'], password=self.user['password'], trust_id=uuid.uuid4().hex) self.post('/auth/tokens', body=auth_data, expected_status=403) @dependency.requires('revoke_api') class TestTrustAuth(TestAuthInfo): EXTENSION_NAME = 'revoke' EXTENSION_TO_ADD = 'revoke_extension' def config_overrides(self): super(TestTrustAuth, self).config_overrides() self.config_fixture.config( group='revoke', driver='keystone.contrib.revoke.backends.kvs.Revoke') self.config_fixture.config( group='token', provider='keystone.token.providers.pki.Provider', revoke_by_id=False) self.config_fixture.config(group='trust', enabled=True) def setUp(self): super(TestTrustAuth, self).setUp() # create a trustee to delegate stuff to self.trustee_user_id = uuid.uuid4().hex self.trustee_user = self.new_user_ref(domain_id=self.domain_id) self.trustee_user['id'] = self.trustee_user_id self.identity_api.create_user(self.trustee_user_id, self.trustee_user) def test_create_trust_400(self): # The server returns a 403 Forbidden rather than a 400, see bug 1133435 self.post('/OS-TRUST/trusts', body={'trust': {}}, expected_status=403) def test_create_unscoped_trust(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) self.assertValidTrustResponse(r, ref) def test_create_trust_no_roles(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=403) def _initialize_test_consume_trust(self, count): # Make sure remaining_uses is decremented as we consume the trust ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, remaining_uses=count, role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) # make sure the trust exists trust = self.assertValidTrustResponse(r, ref) r = self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=200) # get a token for the trustee auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password']) r = self.post('/auth/tokens', body=auth_data, expected_status=201) token = r.headers.get('X-Subject-Token') # get a trust token, consume one use auth_data = self.build_authentication_request( token=token, trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data, expected_status=201) return trust def test_consume_trust_once(self): trust = self._initialize_test_consume_trust(2) # check decremented value r = self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=200) trust = r.result.get('trust') self.assertIsNotNone(trust) self.assertEqual(trust['remaining_uses'], 1) def test_create_one_time_use_trust(self): trust = self._initialize_test_consume_trust(1) # No more uses, the trust is made unavailable self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=404) # this time we can't get a trust token auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_create_trust_with_bad_values_for_remaining_uses(self): # negative values for the remaining_uses parameter are forbidden self._create_trust_with_bad_remaining_use(bad_value=-1) # 0 is a forbidden value as well self._create_trust_with_bad_remaining_use(bad_value=0) # as are non integer values self._create_trust_with_bad_remaining_use(bad_value="a bad value") self._create_trust_with_bad_remaining_use(bad_value=7.2) def _create_trust_with_bad_remaining_use(self, bad_value): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, remaining_uses=bad_value, role_ids=[self.role_id]) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=400) def test_create_unlimited_use_trust(self): # by default trusts are unlimited in terms of tokens that can be # generated from them, this test creates such a trust explicitly ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, remaining_uses=None, role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r, ref) r = self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=200) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password']) r = self.post('/auth/tokens', body=auth_data, expected_status=201) token = r.headers.get('X-Subject-Token') auth_data = self.build_authentication_request( token=token, trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data, expected_status=201) r = self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=200) trust = r.result.get('trust') self.assertIsNone(trust['remaining_uses']) def test_trust_crud(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r, ref) r = self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=200) self.assertValidTrustResponse(r, ref) # validate roles on the trust r = self.get( '/OS-TRUST/trusts/%(trust_id)s/roles' % { 'trust_id': trust['id']}, expected_status=200) roles = self.assertValidRoleListResponse(r, self.role) self.assertIn(self.role['id'], [x['id'] for x in roles]) self.head( '/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % { 'trust_id': trust['id'], 'role_id': self.role['id']}, expected_status=204) r = self.get( '/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % { 'trust_id': trust['id'], 'role_id': self.role['id']}, expected_status=200) self.assertValidRoleResponse(r, self.role) r = self.get('/OS-TRUST/trusts', expected_status=200) self.assertValidTrustListResponse(r, trust) # trusts are immutable self.patch( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, body={'trust': ref}, expected_status=404) self.delete( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=204) self.get( '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']}, expected_status=404) def test_create_trust_trustee_404(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=uuid.uuid4().hex, project_id=self.project_id, role_ids=[self.role_id]) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=404) def test_create_trust_trustor_trustee_backwards(self): ref = self.new_trust_ref( trustor_user_id=self.trustee_user_id, trustee_user_id=self.user_id, project_id=self.project_id, role_ids=[self.role_id]) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=403) def test_create_trust_project_404(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=uuid.uuid4().hex, role_ids=[self.role_id]) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=404) def test_create_trust_role_id_404(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, role_ids=[uuid.uuid4().hex]) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=404) def test_create_trust_role_name_404(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, role_names=[uuid.uuid4().hex]) del ref['id'] self.post('/OS-TRUST/trusts', body={'trust': ref}, expected_status=404) def test_create_expired_trust(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, expires=dict(seconds=-1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r, ref) self.get('/OS-TRUST/trusts/%(trust_id)s' % { 'trust_id': trust['id']}, expected_status=404) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_v3_v2_intermix_trustor_not_in_default_domain_failed(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.default_domain_user_id, project_id=self.project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse( r, self.default_domain_user) token = r.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) self.admin_request( path=path, token='ADMIN', method='GET', expected_status=401) def test_v3_v2_intermix_trustor_not_in_default_domaini_failed(self): ref = self.new_trust_ref( trustor_user_id=self.default_domain_user_id, trustee_user_id=self.trustee_user_id, project_id=self.default_domain_project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.default_domain_project_id) r = self.post('/auth/tokens', body=auth_data) token = r.headers.get('X-Subject-Token') r = self.post('/OS-TRUST/trusts', body={'trust': ref}, token=token) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse( r, self.trustee_user) token = r.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) self.admin_request( path=path, token='ADMIN', method='GET', expected_status=401) def test_v3_v2_intermix_project_not_in_default_domaini_failed(self): # create a trustee in default domain to delegate stuff to trustee_user_id = uuid.uuid4().hex trustee_user = self.new_user_ref(domain_id=test_v3.DEFAULT_DOMAIN_ID) trustee_user['id'] = trustee_user_id self.identity_api.create_user(trustee_user_id, trustee_user) ref = self.new_trust_ref( trustor_user_id=self.default_domain_user_id, trustee_user_id=trustee_user_id, project_id=self.project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.default_domain_project_id) r = self.post('/auth/tokens', body=auth_data) token = r.headers.get('X-Subject-Token') r = self.post('/OS-TRUST/trusts', body={'trust': ref}, token=token) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=trustee_user['id'], password=trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse( r, trustee_user) token = r.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) self.admin_request( path=path, token='ADMIN', method='GET', expected_status=401) def test_v3_v2_intermix(self): # create a trustee in default domain to delegate stuff to trustee_user_id = uuid.uuid4().hex trustee_user = self.new_user_ref(domain_id=test_v3.DEFAULT_DOMAIN_ID) trustee_user['id'] = trustee_user_id self.identity_api.create_user(trustee_user_id, trustee_user) ref = self.new_trust_ref( trustor_user_id=self.default_domain_user_id, trustee_user_id=trustee_user_id, project_id=self.default_domain_project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.default_domain_project_id) r = self.post('/auth/tokens', body=auth_data) token = r.headers.get('X-Subject-Token') r = self.post('/OS-TRUST/trusts', body={'trust': ref}, token=token) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=trustee_user['id'], password=trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse( r, trustee_user) token = r.headers.get('X-Subject-Token') # now validate the v3 token with v2 API path = '/v2.0/tokens/%s' % (token) self.admin_request( path=path, token='ADMIN', method='GET', expected_status=200) def test_exercise_trust_scoped_token_without_impersonation(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse(r, self.trustee_user) self.assertEqual(r.result['token']['user']['id'], self.trustee_user['id']) self.assertEqual(r.result['token']['user']['name'], self.trustee_user['name']) self.assertEqual(r.result['token']['user']['domain']['id'], self.domain['id']) self.assertEqual(r.result['token']['user']['domain']['name'], self.domain['name']) self.assertEqual(r.result['token']['project']['id'], self.project['id']) self.assertEqual(r.result['token']['project']['name'], self.project['name']) def test_exercise_trust_scoped_token_with_impersonation(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=True, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse(r, self.user) self.assertEqual(r.result['token']['user']['id'], self.user['id']) self.assertEqual(r.result['token']['user']['name'], self.user['name']) self.assertEqual(r.result['token']['user']['domain']['id'], self.domain['id']) self.assertEqual(r.result['token']['user']['domain']['name'], self.domain['name']) self.assertEqual(r.result['token']['project']['id'], self.project['id']) self.assertEqual(r.result['token']['project']['name'], self.project['name']) def assertTrustTokensRevoked(self, trust_id): revocation_response = self.get('/OS-REVOKE/events', expected_status=200) revocation_events = revocation_response.json_body['events'] found = False for event in revocation_events: if event.get('OS-TRUST:trust_id') == trust_id: found = True self.assertTrue(found, 'event with trust_id %s not found in list' % trust_id) def test_delete_trust_revokes_tokens(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) trust_id = trust['id'] auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust_id) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse( r, self.trustee_user) trust_token = r.headers['X-Subject-Token'] self.delete('/OS-TRUST/trusts/%(trust_id)s' % { 'trust_id': trust_id}, expected_status=204) headers = {'X-Subject-Token': trust_token} self.head('/auth/tokens', headers=headers, expected_status=404) self.assertTrustTokensRevoked(trust_id) def test_delete_trust(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r, ref) self.delete('/OS-TRUST/trusts/%(trust_id)s' % { 'trust_id': trust['id']}, expected_status=204) self.get('/OS-TRUST/trusts/%(trust_id)s' % { 'trust_id': trust['id']}, expected_status=404) self.get('/OS-TRUST/trusts/%(trust_id)s' % { 'trust_id': trust['id']}, expected_status=404) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) self.post('/auth/tokens', body=auth_data, expected_status=401) def test_list_trusts(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=False, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] for i in range(3): r = self.post('/OS-TRUST/trusts', body={'trust': ref}) self.assertValidTrustResponse(r, ref) r = self.get('/OS-TRUST/trusts', expected_status=200) trusts = r.result['trusts'] self.assertEqual(3, len(trusts)) self.assertValidTrustListResponse(r) r = self.get('/OS-TRUST/trusts?trustor_user_id=%s' % self.user_id, expected_status=200) trusts = r.result['trusts'] self.assertEqual(3, len(trusts)) self.assertValidTrustListResponse(r) r = self.get('/OS-TRUST/trusts?trustee_user_id=%s' % self.user_id, expected_status=200) trusts = r.result['trusts'] self.assertEqual(0, len(trusts)) def test_change_password_invalidates_trust_tokens(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=True, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse(r, self.user) trust_token = r.headers.get('X-Subject-Token') self.get('/OS-TRUST/trusts?trustor_user_id=%s' % self.user_id, expected_status=200, token=trust_token) self.assertValidUserResponse( self.patch('/users/%s' % self.trustee_user['id'], body={'user': {'password': uuid.uuid4().hex}}, expected_status=200)) self.get('/OS-TRUST/trusts?trustor_user_id=%s' % self.user_id, expected_status=401, token=trust_token) def test_trustee_can_do_role_ops(self): ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=True, role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password']) r = self.get( '/OS-TRUST/trusts/%(trust_id)s/roles' % { 'trust_id': trust['id']}, auth=auth_data) self.assertValidRoleListResponse(r, self.role) self.head( '/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % { 'trust_id': trust['id'], 'role_id': self.role['id']}, auth=auth_data, expected_status=204) r = self.get( '/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % { 'trust_id': trust['id'], 'role_id': self.role['id']}, auth=auth_data, expected_status=200) self.assertValidRoleResponse(r, self.role) class TestAPIProtectionWithoutAuthContextMiddleware(test_v3.RestfulTestCase): def test_api_protection_with_no_auth_context_in_env(self): auth_data = self.build_authentication_request( user_id=self.default_domain_user['id'], password=self.default_domain_user['password'], project_id=self.project['id']) resp = self.post('/auth/tokens', body=auth_data) token = resp.headers.get('X-Subject-Token') auth_controller = auth.controllers.Auth() # all we care is that auth context is not in the environment and # 'token_id' is used to build the auth context instead context = {'subject_token_id': token, 'token_id': token, 'query_string': {}, 'environment': {}} r = auth_controller.validate_token(context) self.assertEqual(200, r.status_code) keystone-2014.1/keystone/tests/test_injection.py0000664000175400017540000001776312323716272023221 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import testtools import uuid from keystone.common import dependency class TestDependencyInjection(testtools.TestCase): def setUp(self): super(TestDependencyInjection, self).setUp() self.addCleanup(dependency.reset) def test_dependency_injection(self): class Interface(object): def do_work(self): assert False @dependency.provider('first_api') class FirstImplementation(Interface): def do_work(self): return True @dependency.provider('second_api') class SecondImplementation(Interface): def do_work(self): return True @dependency.requires('first_api', 'second_api') class Consumer(object): def do_work_with_dependencies(self): assert self.first_api.do_work() assert self.second_api.do_work() # initialize dependency providers first_api = FirstImplementation() second_api = SecondImplementation() # ... sometime later, initialize a dependency consumer consumer = Consumer() # the expected dependencies should be available to the consumer self.assertIs(consumer.first_api, first_api) self.assertIs(consumer.second_api, second_api) self.assertIsInstance(consumer.first_api, Interface) self.assertIsInstance(consumer.second_api, Interface) consumer.do_work_with_dependencies() def test_dependency_provider_configuration(self): @dependency.provider('api') class Configurable(object): def __init__(self, value=None): self.value = value def get_value(self): return self.value @dependency.requires('api') class Consumer(object): def get_value(self): return self.api.get_value() # initialize dependency providers api = Configurable(value=True) # ... sometime later, initialize a dependency consumer consumer = Consumer() # the expected dependencies should be available to the consumer self.assertIs(consumer.api, api) self.assertIsInstance(consumer.api, Configurable) self.assertTrue(consumer.get_value()) def test_dependency_consumer_configuration(self): @dependency.provider('api') class Provider(object): def get_value(self): return True @dependency.requires('api') class Configurable(object): def __init__(self, value=None): self.value = value def get_value(self): if self.value: return self.api.get_value() # initialize dependency providers api = Provider() # ... sometime later, initialize a dependency consumer consumer = Configurable(value=True) # the expected dependencies should be available to the consumer self.assertIs(consumer.api, api) self.assertIsInstance(consumer.api, Provider) self.assertTrue(consumer.get_value()) def test_inherited_dependency(self): class Interface(object): def do_work(self): assert False @dependency.provider('first_api') class FirstImplementation(Interface): def do_work(self): return True @dependency.provider('second_api') class SecondImplementation(Interface): def do_work(self): return True @dependency.requires('first_api') class ParentConsumer(object): def do_work_with_dependencies(self): assert self.first_api.do_work() @dependency.requires('second_api') class ChildConsumer(ParentConsumer): def do_work_with_dependencies(self): assert self.second_api.do_work() super(ChildConsumer, self).do_work_with_dependencies() # initialize dependency providers first_api = FirstImplementation() second_api = SecondImplementation() # ... sometime later, initialize a dependency consumer consumer = ChildConsumer() # dependencies should be naturally inherited self.assertEqual( ParentConsumer._dependencies, set(['first_api'])) self.assertEqual( ChildConsumer._dependencies, set(['first_api', 'second_api'])) self.assertEqual( consumer._dependencies, set(['first_api', 'second_api'])) # the expected dependencies should be available to the consumer self.assertIs(consumer.first_api, first_api) self.assertIs(consumer.second_api, second_api) self.assertIsInstance(consumer.first_api, Interface) self.assertIsInstance(consumer.second_api, Interface) consumer.do_work_with_dependencies() def test_unresolvable_dependency(self): @dependency.requires(uuid.uuid4().hex) class Consumer(object): pass def for_test(): Consumer() dependency.resolve_future_dependencies() self.assertRaises(dependency.UnresolvableDependencyException, for_test) def test_circular_dependency(self): p1_name = uuid.uuid4().hex p2_name = uuid.uuid4().hex @dependency.provider(p1_name) @dependency.requires(p2_name) class P1(object): pass @dependency.provider(p2_name) @dependency.requires(p1_name) class P2(object): pass p1 = P1() p2 = P2() dependency.resolve_future_dependencies() self.assertIs(getattr(p1, p2_name), p2) self.assertIs(getattr(p2, p1_name), p1) def test_reset(self): # Can reset the registry of providers. p_id = uuid.uuid4().hex @dependency.provider(p_id) class P(object): pass p_inst = P() self.assertIs(dependency.REGISTRY[p_id], p_inst) dependency.reset() self.assertFalse(dependency.REGISTRY) def test_optional_dependency_not_provided(self): requirement_name = uuid.uuid4().hex @dependency.optional(requirement_name) class C1(object): pass c1_inst = C1() dependency.resolve_future_dependencies() self.assertIsNone(getattr(c1_inst, requirement_name)) def test_optional_dependency_provided(self): requirement_name = uuid.uuid4().hex @dependency.optional(requirement_name) class C1(object): pass @dependency.provider(requirement_name) class P1(object): pass c1_inst = C1() p1_inst = P1() dependency.resolve_future_dependencies() self.assertIs(getattr(c1_inst, requirement_name), p1_inst) def test_optional_and_required(self): p1_name = uuid.uuid4().hex p2_name = uuid.uuid4().hex optional_name = uuid.uuid4().hex @dependency.provider(p1_name) @dependency.requires(p2_name) @dependency.optional(optional_name) class P1(object): pass @dependency.provider(p2_name) @dependency.requires(p1_name) class P2(object): pass p1 = P1() p2 = P2() dependency.resolve_future_dependencies() self.assertIs(getattr(p1, p2_name), p2) self.assertIs(getattr(p2, p1_name), p1) self.assertIsNone(getattr(p1, optional_name)) keystone-2014.1/keystone/tests/test_v3_credential.py0000664000175400017540000003552612323716267023762 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import hashlib import json import uuid from keystoneclient.contrib.ec2 import utils as ec2_utils from keystone import config from keystone import exception from keystone.tests import test_v3 CONF = config.CONF class CredentialBaseTestCase(test_v3.RestfulTestCase): def _create_dict_blob_credential(self): blob = {"access": uuid.uuid4().hex, "secret": uuid.uuid4().hex} credential_id = hashlib.sha256(blob['access']).hexdigest() credential = self.new_credential_ref( user_id=self.user['id'], project_id=self.project_id) credential['id'] = credential_id # Store the blob as a dict *not* JSON ref bug #1259584 # This means we can test the dict->json workaround, added # as part of the bugfix for backwards compatibility works. credential['blob'] = blob credential['type'] = 'ec2' # Create direct via the DB API to avoid validation failure self.credential_api.create_credential( credential_id, credential) expected_blob = json.dumps(blob) return expected_blob, credential_id class CredentialTestCase(CredentialBaseTestCase): """Test credential CRUD.""" def setUp(self): super(CredentialTestCase, self).setUp() self.credential_id = uuid.uuid4().hex self.credential = self.new_credential_ref( user_id=self.user['id'], project_id=self.project_id) self.credential['id'] = self.credential_id self.credential_api.create_credential( self.credential_id, self.credential) def test_credential_api_delete_credentials_for_project(self): self.credential_api.delete_credentials_for_project(self.project_id) # Test that the credential that we created in .setUp no longer exists # once we delete all credentials for self.project_id self.assertRaises(exception.CredentialNotFound, self.credential_api.get_credential, credential_id=self.credential_id) def test_credential_api_delete_credentials_for_user(self): self.credential_api.delete_credentials_for_user(self.user_id) # Test that the credential that we created in .setUp no longer exists # once we delete all credentials for self.user_id self.assertRaises(exception.CredentialNotFound, self.credential_api.get_credential, credential_id=self.credential_id) def test_list_credentials(self): """Call ``GET /credentials``.""" r = self.get('/credentials') self.assertValidCredentialListResponse(r, ref=self.credential) def test_list_credentials_xml(self): """Call ``GET /credentials`` (xml data).""" r = self.get('/credentials', content_type='xml') self.assertValidCredentialListResponse(r, ref=self.credential) def test_create_credential(self): """Call ``POST /credentials``.""" ref = self.new_credential_ref(user_id=self.user['id']) r = self.post( '/credentials', body={'credential': ref}) self.assertValidCredentialResponse(r, ref) def test_get_credential(self): """Call ``GET /credentials/{credential_id}``.""" r = self.get( '/credentials/%(credential_id)s' % { 'credential_id': self.credential_id}) self.assertValidCredentialResponse(r, self.credential) def test_update_credential(self): """Call ``PATCH /credentials/{credential_id}``.""" ref = self.new_credential_ref( user_id=self.user['id'], project_id=self.project_id) del ref['id'] r = self.patch( '/credentials/%(credential_id)s' % { 'credential_id': self.credential_id}, body={'credential': ref}) self.assertValidCredentialResponse(r, ref) def test_delete_credential(self): """Call ``DELETE /credentials/{credential_id}``.""" self.delete( '/credentials/%(credential_id)s' % { 'credential_id': self.credential_id}) def test_create_ec2_credential(self): """Call ``POST /credentials`` for creating ec2 credential.""" ref = self.new_credential_ref(user_id=self.user['id']) blob = {"access": uuid.uuid4().hex, "secret": uuid.uuid4().hex} ref['blob'] = json.dumps(blob) ref['type'] = 'ec2' r = self.post( '/credentials', body={'credential': ref}) self.assertValidCredentialResponse(r, ref) # Assert credential id is same as hash of access key id for # ec2 credentials self.assertEqual(r.result['credential']['id'], hashlib.sha256(blob['access']).hexdigest()) # Create second ec2 credential with the same access key id and check # for conflict. self.post( '/credentials', body={'credential': ref}, expected_status=409) def test_get_ec2_dict_blob(self): """Ensure non-JSON blob data is correctly converted.""" expected_blob, credential_id = self._create_dict_blob_credential() r = self.get( '/credentials/%(credential_id)s' % { 'credential_id': credential_id}) self.assertEqual(expected_blob, r.result['credential']['blob']) def test_list_ec2_dict_blob(self): """Ensure non-JSON blob data is correctly converted.""" expected_blob, credential_id = self._create_dict_blob_credential() list_r = self.get('/credentials') list_creds = list_r.result['credentials'] list_ids = [r['id'] for r in list_creds] self.assertIn(credential_id, list_ids) for r in list_creds: if r['id'] == credential_id: self.assertEqual(expected_blob, r['blob']) def test_create_non_ec2_credential(self): """Call ``POST /credentials`` for creating non-ec2 credential.""" ref = self.new_credential_ref(user_id=self.user['id']) blob = {"access": uuid.uuid4().hex, "secret": uuid.uuid4().hex} ref['blob'] = json.dumps(blob) r = self.post( '/credentials', body={'credential': ref}) self.assertValidCredentialResponse(r, ref) # Assert credential id is not same as hash of access key id for # non-ec2 credentials self.assertNotEqual(r.result['credential']['id'], hashlib.sha256(blob['access']).hexdigest()) def test_create_ec2_credential_with_invalid_blob(self): """Call ``POST /credentials`` for creating ec2 credential with invalid blob. """ ref = self.new_credential_ref(user_id=self.user['id']) ref['blob'] = '{"abc":"def"d}' ref['type'] = 'ec2' # Assert 400 status for bad request containing invalid # blob response = self.post( '/credentials', body={'credential': ref}, expected_status=400) self.assertValidErrorResponse(response) def test_create_credential_with_admin_token(self): # Make sure we can create credential with the static admin token ref = self.new_credential_ref(user_id=self.user['id']) r = self.post( '/credentials', body={'credential': ref}, token=CONF.admin_token) self.assertValidCredentialResponse(r, ref) class TestCredentialTrustScoped(test_v3.RestfulTestCase): """Test credential with trust scoped token.""" def setUp(self): super(TestCredentialTrustScoped, self).setUp() self.trustee_user_id = uuid.uuid4().hex self.trustee_user = self.new_user_ref(domain_id=self.domain_id) self.trustee_user['id'] = self.trustee_user_id self.identity_api.create_user(self.trustee_user_id, self.trustee_user) def config_overrides(self): super(TestCredentialTrustScoped, self).config_overrides() self.config_fixture.config(group='trust', enabled=True) def test_trust_scoped_ec2_credential(self): """Call ``POST /credentials`` for creating ec2 credential.""" # Create the trust ref = self.new_trust_ref( trustor_user_id=self.user_id, trustee_user_id=self.trustee_user_id, project_id=self.project_id, impersonation=True, expires=dict(minutes=1), role_ids=[self.role_id]) del ref['id'] r = self.post('/OS-TRUST/trusts', body={'trust': ref}) trust = self.assertValidTrustResponse(r) # Get a trust scoped token auth_data = self.build_authentication_request( user_id=self.trustee_user['id'], password=self.trustee_user['password'], trust_id=trust['id']) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectTrustScopedTokenResponse(r, self.user) trust_id = r.result['token']['OS-TRUST:trust']['id'] token_id = r.headers.get('X-Subject-Token') # Create the credential with the trust scoped token ref = self.new_credential_ref(user_id=self.user['id']) blob = {"access": uuid.uuid4().hex, "secret": uuid.uuid4().hex} ref['blob'] = json.dumps(blob) ref['type'] = 'ec2' r = self.post( '/credentials', body={'credential': ref}, token=token_id) # We expect the response blob to contain the trust_id ret_ref = ref.copy() ret_blob = blob.copy() ret_blob['trust_id'] = trust_id ret_ref['blob'] = json.dumps(ret_blob) self.assertValidCredentialResponse(r, ref=ret_ref) # Assert credential id is same as hash of access key id for # ec2 credentials self.assertEqual(r.result['credential']['id'], hashlib.sha256(blob['access']).hexdigest()) # Create second ec2 credential with the same access key id and check # for conflict. self.post( '/credentials', body={'credential': ref}, token=token_id, expected_status=409) class TestCredentialEc2(CredentialBaseTestCase): """Test v3 credential compatibility with ec2tokens.""" def setUp(self): super(TestCredentialEc2, self).setUp() def _validate_signature(self, access, secret): """Test signature validation with the access/secret provided.""" signer = ec2_utils.Ec2Signer(secret) params = {'SignatureMethod': 'HmacSHA256', 'SignatureVersion': '2', 'AWSAccessKeyId': access} request = {'host': 'foo', 'verb': 'GET', 'path': '/bar', 'params': params} signature = signer.generate(request) # Now make a request to validate the signed dummy request via the # ec2tokens API. This proves the v3 ec2 credentials actually work. sig_ref = {'access': access, 'signature': signature, 'host': 'foo', 'verb': 'GET', 'path': '/bar', 'params': params} r = self.post( '/ec2tokens', body={'ec2Credentials': sig_ref}, expected_status=200) self.assertValidTokenResponse(r) def test_ec2_credential_signature_validate(self): """Test signature validation with a v3 ec2 credential.""" ref = self.new_credential_ref( user_id=self.user['id'], project_id=self.project_id) blob = {"access": uuid.uuid4().hex, "secret": uuid.uuid4().hex} ref['blob'] = json.dumps(blob) ref['type'] = 'ec2' r = self.post( '/credentials', body={'credential': ref}) self.assertValidCredentialResponse(r, ref) # Assert credential id is same as hash of access key id self.assertEqual(r.result['credential']['id'], hashlib.sha256(blob['access']).hexdigest()) cred_blob = json.loads(r.result['credential']['blob']) self.assertEqual(blob, cred_blob) self._validate_signature(access=cred_blob['access'], secret=cred_blob['secret']) def test_ec2_credential_signature_validate_legacy(self): """Test signature validation with a legacy v3 ec2 credential.""" cred_json, credential_id = self._create_dict_blob_credential() cred_blob = json.loads(cred_json) self._validate_signature(access=cred_blob['access'], secret=cred_blob['secret']) def _get_ec2_cred_uri(self): return '/users/%s/credentials/OS-EC2' % self.user_id def _get_ec2_cred(self): uri = self._get_ec2_cred_uri() r = self.post(uri, body={'tenant_id': self.project_id}) return r.result['credential'] def test_ec2_create_credential(self): """Test ec2 credential creation.""" ec2_cred = self._get_ec2_cred() self.assertEqual(self.user_id, ec2_cred['user_id']) self.assertEqual(self.project_id, ec2_cred['tenant_id']) self.assertIsNone(ec2_cred['trust_id']) self._validate_signature(access=ec2_cred['access'], secret=ec2_cred['secret']) return ec2_cred def test_ec2_get_credential(self): ec2_cred = self._get_ec2_cred() uri = '/'.join([self._get_ec2_cred_uri(), ec2_cred['access']]) r = self.get(uri) self.assertDictEqual(ec2_cred, r.result['credential']) def test_ec2_list_credentials(self): """Test ec2 credential listing.""" self._get_ec2_cred_uri() uri = self._get_ec2_cred_uri() r = self.get(uri) cred_list = r.result self.assertEqual(1, len(cred_list)) def test_ec2_delete_credential(self): """Test ec2 credential deletion.""" ec2_cred = self._get_ec2_cred() uri = '/'.join([self._get_ec2_cred_uri(), ec2_cred['access']]) cred_from_credential_api = self.credential_api.list_credentials( user_id=self.user_id) self.assertEqual(1, len(cred_from_credential_api)) self.delete(uri) self.assertRaises(exception.CredentialNotFound, self.credential_api.get_credential, cred_from_credential_api[0]['id']) keystone-2014.1/keystone/tests/test_cert_setup.py0000664000175400017540000001163112323716272023400 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import os import shutil from keystone.common import openssl from keystone import exception from keystone import tests from keystone.tests import default_fixtures from keystone.tests import rest from keystone import token SSLDIR = tests.dirs.tmp('ssl') CONF = tests.CONF DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id CERTDIR = os.path.join(SSLDIR, 'certs') KEYDIR = os.path.join(SSLDIR, 'private') class CertSetupTestCase(rest.RestfulTestCase): def setUp(self): super(CertSetupTestCase, self).setUp() self.load_backends() self.load_fixtures(default_fixtures) self.controller = token.controllers.Auth() def cleanup_ssldir(): try: shutil.rmtree(SSLDIR) except OSError: pass self.addCleanup(cleanup_ssldir) def config_overrides(self): super(CertSetupTestCase, self).config_overrides() ca_certs = os.path.join(CERTDIR, 'ca.pem') ca_key = os.path.join(CERTDIR, 'cakey.pem') self.config_fixture.config( group='signing', certfile=os.path.join(CERTDIR, 'signing_cert.pem'), ca_certs=ca_certs, ca_key=ca_key, keyfile=os.path.join(KEYDIR, 'signing_key.pem')) self.config_fixture.config( group='ssl', ca_certs=ca_certs, ca_key=ca_key, certfile=os.path.join(CERTDIR, 'keystone.pem'), keyfile=os.path.join(KEYDIR, 'keystonekey.pem')) def test_can_handle_missing_certs(self): self.config_fixture.config(group='signing', certfile='invalid') user = { 'id': 'fake1', 'name': 'fake1', 'password': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID } body_dict = { 'passwordCredentials': { 'userId': user['id'], 'password': user['password'], }, } self.identity_api.create_user(user['id'], user) self.assertRaises(exception.UnexpectedError, self.controller.authenticate, {}, body_dict) def test_create_pki_certs(self): pki = openssl.ConfigurePKI(None, None) pki.run() self.assertTrue(os.path.exists(CONF.signing.certfile)) self.assertTrue(os.path.exists(CONF.signing.ca_certs)) self.assertTrue(os.path.exists(CONF.signing.keyfile)) def test_create_ssl_certs(self): ssl = openssl.ConfigureSSL(None, None) ssl.run() self.assertTrue(os.path.exists(CONF.ssl.ca_certs)) self.assertTrue(os.path.exists(CONF.ssl.certfile)) self.assertTrue(os.path.exists(CONF.ssl.keyfile)) def test_fetch_signing_cert(self): pki = openssl.ConfigurePKI(None, None) pki.run() # NOTE(jamielennox): Use request directly because certificate # requests don't have some of the normal information signing_resp = self.request(self.public_app, '/v2.0/certificates/signing', method='GET', expected_status=200) cacert_resp = self.request(self.public_app, '/v2.0/certificates/ca', method='GET', expected_status=200) with open(CONF.signing.certfile) as f: self.assertEqual(signing_resp.text, f.read()) with open(CONF.signing.ca_certs) as f: self.assertEqual(cacert_resp.text, f.read()) # NOTE(jamielennox): This is weird behaviour that we need to enforce. # It doesn't matter what you ask for it's always going to give text # with a text/html content_type. for path in ['/v2.0/certificates/signing', '/v2.0/certificates/ca']: for accept in [None, 'text/html', 'application/json', 'text/xml']: headers = {'Accept': accept} if accept else {} resp = self.request(self.public_app, path, method='GET', expected_status=200, headers=headers) self.assertEqual(resp.content_type, 'text/html') def test_failure(self): for path in ['/v2.0/certificates/signing', '/v2.0/certificates/ca']: self.request(self.public_app, path, method='GET', expected_status=500) keystone-2014.1/keystone/tests/test_backend.py0000664000175400017540000060217212323716272022620 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import copy import datetime import hashlib import mock import uuid import six from testtools import matchers from keystone.catalog import core from keystone.common import driver_hints from keystone import config from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import default_fixtures from keystone.tests import filtering from keystone.tests import test_utils from keystone.token import provider CONF = config.CONF DEFAULT_DOMAIN_ID = CONF.identity.default_domain_id TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' NULL_OBJECT = object() class IdentityTests(object): def _get_domain_fixture(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain['id'], domain) return domain def test_project_add_and_remove_user_role(self): user_ids = self.assignment_api.list_user_ids_for_project( self.tenant_bar['id']) self.assertNotIn(self.user_two['id'], user_ids) self.assignment_api.add_role_to_user_and_project( tenant_id=self.tenant_bar['id'], user_id=self.user_two['id'], role_id=self.role_other['id']) user_ids = self.assignment_api.list_user_ids_for_project( self.tenant_bar['id']) self.assertIn(self.user_two['id'], user_ids) self.assignment_api.remove_role_from_user_and_project( tenant_id=self.tenant_bar['id'], user_id=self.user_two['id'], role_id=self.role_other['id']) user_ids = self.assignment_api.list_user_ids_for_project( self.tenant_bar['id']) self.assertNotIn(self.user_two['id'], user_ids) def test_remove_user_role_not_assigned(self): # Expect failure if attempt to remove a role that was never assigned to # the user. self.assertRaises(exception.RoleNotFound, self.assignment_api. remove_role_from_user_and_project, tenant_id=self.tenant_bar['id'], user_id=self.user_two['id'], role_id=self.role_other['id']) def test_authenticate_bad_user(self): self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id=uuid.uuid4().hex, password=self.user_foo['password']) def test_authenticate_bad_password(self): self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id=self.user_foo['id'], password=uuid.uuid4().hex) def test_authenticate(self): user_ref = self.identity_api.authenticate( context={}, user_id=self.user_sna['id'], password=self.user_sna['password']) # NOTE(termie): the password field is left in user_sna to make # it easier to authenticate in tests, but should # not be returned by the api self.user_sna.pop('password') self.user_sna['enabled'] = True self.assertDictEqual(user_ref, self.user_sna) def test_authenticate_and_get_roles_no_metadata(self): user = { 'id': 'no_meta', 'name': 'NO_META', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'no_meta2', } self.identity_api.create_user(user['id'], user) self.assignment_api.add_user_to_project(self.tenant_baz['id'], user['id']) user_ref = self.identity_api.authenticate( context={}, user_id=user['id'], password=user['password']) self.assertNotIn('password', user_ref) # NOTE(termie): the password field is left in user_sna to make # it easier to authenticate in tests, but should # not be returned by the api user.pop('password') self.assertDictContainsSubset(user, user_ref) role_list = self.assignment_api.get_roles_for_user_and_project( user['id'], self.tenant_baz['id']) self.assertEqual(len(role_list), 1) self.assertIn(CONF.member_role_id, role_list) def test_authenticate_if_no_password_set(self): id_ = uuid.uuid4().hex user = { 'id': id_, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, } self.identity_api.create_user(user['id'], user) self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id=id_, password='password') def test_password_hashed(self): driver = self.identity_api._select_identity_driver( self.user_foo['domain_id']) user_ref = driver._get_user(self.user_foo['id']) self.assertNotEqual(user_ref['password'], self.user_foo['password']) def test_create_unicode_user_name(self): unicode_name = u'name \u540d\u5b57' user = {'id': uuid.uuid4().hex, 'name': unicode_name, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} ref = self.identity_api.create_user(user['id'], user) self.assertEqual(unicode_name, ref['name']) def test_get_project(self): tenant_ref = self.assignment_api.get_project(self.tenant_bar['id']) self.assertDictEqual(tenant_ref, self.tenant_bar) def test_get_project_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, uuid.uuid4().hex) def test_get_project_by_name(self): tenant_ref = self.assignment_api.get_project_by_name( self.tenant_bar['name'], DEFAULT_DOMAIN_ID) self.assertDictEqual(tenant_ref, self.tenant_bar) def test_get_project_by_name_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project_by_name, uuid.uuid4().hex, DEFAULT_DOMAIN_ID) def test_list_user_ids_for_project(self): user_ids = self.assignment_api.list_user_ids_for_project( self.tenant_baz['id']) self.assertEqual(len(user_ids), 2) self.assertIn(self.user_two['id'], user_ids) self.assertIn(self.user_badguy['id'], user_ids) def test_get_project_user_ids_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.list_user_ids_for_project, uuid.uuid4().hex) def test_get_user(self): user_ref = self.identity_api.get_user(self.user_foo['id']) # NOTE(termie): the password field is left in user_foo to make # it easier to authenticate in tests, but should # not be returned by the api self.user_foo.pop('password') self.assertDictEqual(user_ref, self.user_foo) def test_get_user_404(self): self.assertRaises(exception.UserNotFound, self.identity_api.get_user, uuid.uuid4().hex) def test_get_user_by_name(self): user_ref = self.identity_api.get_user_by_name( self.user_foo['name'], DEFAULT_DOMAIN_ID) # NOTE(termie): the password field is left in user_foo to make # it easier to authenticate in tests, but should # not be returned by the api self.user_foo.pop('password') self.assertDictEqual(user_ref, self.user_foo) def test_get_user_by_name_404(self): self.assertRaises(exception.UserNotFound, self.identity_api.get_user_by_name, uuid.uuid4().hex, DEFAULT_DOMAIN_ID) def test_get_role(self): role_ref = self.assignment_api.get_role(self.role_admin['id']) role_ref_dict = dict((x, role_ref[x]) for x in role_ref) self.assertDictEqual(role_ref_dict, self.role_admin) def test_get_role_404(self): self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, uuid.uuid4().hex) def test_create_duplicate_role_name_fails(self): role = {'id': 'fake1', 'name': 'fake1name'} self.assignment_api.create_role('fake1', role) role['id'] = 'fake2' self.assertRaises(exception.Conflict, self.assignment_api.create_role, 'fake2', role) def test_rename_duplicate_role_name_fails(self): role1 = { 'id': 'fake1', 'name': 'fake1name' } role2 = { 'id': 'fake2', 'name': 'fake2name' } self.assignment_api.create_role('fake1', role1) self.assignment_api.create_role('fake2', role2) role1['name'] = 'fake2name' self.assertRaises(exception.Conflict, self.assignment_api.update_role, 'fake1', role1) def test_create_duplicate_user_id_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'fakepass', 'tenants': ['bar']} self.identity_api.create_user('fake1', user) user['name'] = 'fake2' self.assertRaises(exception.Conflict, self.identity_api.create_user, 'fake1', user) def test_create_duplicate_user_name_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'fakepass', 'tenants': ['bar']} self.identity_api.create_user('fake1', user) user['id'] = 'fake2' self.assertRaises(exception.Conflict, self.identity_api.create_user, 'fake2', user) def test_create_duplicate_user_name_in_different_domains(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} user2 = {'id': uuid.uuid4().hex, 'name': user1['name'], 'domain_id': new_domain['id'], 'password': uuid.uuid4().hex} self.identity_api.create_user(user1['id'], user1) self.identity_api.create_user(user2['id'], user2) def test_move_user_between_domains(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex} self.identity_api.create_user(user['id'], user) user['domain_id'] = domain2['id'] self.identity_api.update_user(user['id'], user) def test_move_user_between_domains_with_clashing_names_fails(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) # First, create a user in domain1 user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex} self.identity_api.create_user(user1['id'], user1) # Now create a user in domain2 with a potentially clashing # name - which should work since we have domain separation user2 = {'id': uuid.uuid4().hex, 'name': user1['name'], 'domain_id': domain2['id'], 'password': uuid.uuid4().hex} self.identity_api.create_user(user2['id'], user2) # Now try and move user1 into the 2nd domain - which should # fail since the names clash user1['domain_id'] = domain2['id'] self.assertRaises(exception.Conflict, self.identity_api.update_user, user1['id'], user1) def test_rename_duplicate_user_name_fails(self): user1 = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'fakepass', 'tenants': ['bar']} user2 = {'id': 'fake2', 'name': 'fake2', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'fakepass', 'tenants': ['bar']} self.identity_api.create_user('fake1', user1) self.identity_api.create_user('fake2', user2) user2['name'] = 'fake1' self.assertRaises(exception.Conflict, self.identity_api.update_user, 'fake2', user2) def test_update_user_id_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID, 'password': 'fakepass', 'tenants': ['bar']} self.identity_api.create_user('fake1', user) user['id'] = 'fake2' self.assertRaises(exception.ValidationError, self.identity_api.update_user, 'fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['id'], 'fake1') self.assertRaises(exception.UserNotFound, self.identity_api.get_user, 'fake2') def test_create_duplicate_project_id_fails(self): tenant = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant['name'] = 'fake2' self.assertRaises(exception.Conflict, self.assignment_api.create_project, 'fake1', tenant) def test_create_duplicate_project_name_fails(self): tenant = {'id': 'fake1', 'name': 'fake', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant['id'] = 'fake2' self.assertRaises(exception.Conflict, self.assignment_api.create_project, 'fake1', tenant) def test_create_duplicate_project_name_in_different_domains(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) tenant1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} tenant2 = {'id': uuid.uuid4().hex, 'name': tenant1['name'], 'domain_id': new_domain['id']} self.assignment_api.create_project(tenant1['id'], tenant1) self.assignment_api.create_project(tenant2['id'], tenant2) def test_move_project_between_domains(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project['id'], project) project['domain_id'] = domain2['id'] self.assignment_api.update_project(project['id'], project) def test_move_project_between_domains_with_clashing_names_fails(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) # First, create a project in domain1 project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) # Now create a project in domain2 with a potentially clashing # name - which should work since we have domain separation project2 = {'id': uuid.uuid4().hex, 'name': project1['name'], 'domain_id': domain2['id']} self.assignment_api.create_project(project2['id'], project2) # Now try and move project1 into the 2nd domain - which should # fail since the names clash project1['domain_id'] = domain2['id'] self.assertRaises(exception.Conflict, self.assignment_api.update_project, project1['id'], project1) def test_rename_duplicate_project_name_fails(self): tenant1 = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} tenant2 = {'id': 'fake2', 'name': 'fake2', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant1) self.assignment_api.create_project('fake2', tenant2) tenant2['name'] = 'fake1' self.assertRaises(exception.Error, self.assignment_api.update_project, 'fake2', tenant2) def test_update_project_id_does_nothing(self): tenant = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant['id'] = 'fake2' self.assignment_api.update_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual(tenant_ref['id'], 'fake1') self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, 'fake2') def test_list_role_assignments_unfiltered(self): """Test for unfiltered listing role assignments. Test Plan: - Create a domain, with a user, group & project - Find how many role assignments already exist (from default fixtures) - Create a grant of each type (user/group on project/domain) - Check the number of assignments has gone up by 4 and that the entries we added are in the list returned - Check that if we list assignments by role_id, then we get back assignments that only contain that role. """ new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': new_domain['id']} self.assignment_api.create_project(new_project['id'], new_project) # First check how many role grants already exist existing_assignments = len(self.assignment_api.list_role_assignments()) existing_assignments_for_role = len( self.assignment_api.list_role_assignments_for_role( role_id='admin')) # Now create the grants (roles are defined in default_fixtures) self.assignment_api.create_grant(user_id=new_user['id'], domain_id=new_domain['id'], role_id='member') self.assignment_api.create_grant(user_id=new_user['id'], project_id=new_project['id'], role_id='other') self.assignment_api.create_grant(group_id=new_group['id'], domain_id=new_domain['id'], role_id='admin') self.assignment_api.create_grant(group_id=new_group['id'], project_id=new_project['id'], role_id='admin') # Read back the full list of assignments - check it is gone up by 4 assignment_list = self.assignment_api.list_role_assignments() self.assertEqual(len(assignment_list), existing_assignments + 4) # Now check that each of our four new entries are in the list self.assertIn( {'user_id': new_user['id'], 'domain_id': new_domain['id'], 'role_id': 'member'}, assignment_list) self.assertIn( {'user_id': new_user['id'], 'project_id': new_project['id'], 'role_id': 'other'}, assignment_list) self.assertIn( {'group_id': new_group['id'], 'domain_id': new_domain['id'], 'role_id': 'admin'}, assignment_list) self.assertIn( {'group_id': new_group['id'], 'project_id': new_project['id'], 'role_id': 'admin'}, assignment_list) # Read back the list of assignments for just the admin role, checking # this only goes up by two. assignment_list = self.assignment_api.list_role_assignments_for_role( role_id='admin') self.assertEqual(len(assignment_list), existing_assignments_for_role + 2) # Now check that each of our two new entries are in the list self.assertIn( {'group_id': new_group['id'], 'domain_id': new_domain['id'], 'role_id': 'admin'}, assignment_list) self.assertIn( {'group_id': new_group['id'], 'project_id': new_project['id'], 'role_id': 'admin'}, assignment_list) def test_list_role_assignments_bad_role(self): assignment_list = self.assignment_api.list_role_assignments_for_role( role_id=uuid.uuid4().hex) self.assertEqual(assignment_list, []) def test_add_duplicate_role_grant(self): roles_ref = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_bar['id']) self.assertNotIn(self.role_admin['id'], roles_ref) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_admin['id']) self.assertRaises(exception.Conflict, self.assignment_api.add_role_to_user_and_project, self.user_foo['id'], self.tenant_bar['id'], self.role_admin['id']) def test_get_role_by_user_and_project_with_user_in_group(self): """Test for get role by user and project, user was added into a group. Test Plan: - Create a user, a project & a group, add this user to group - Create roles and grant them to user and project - Check the role list get by the user and project was as expected """ user_ref = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user_ref['id'], user_ref) project_ref = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(project_ref['id'], project_ref) group = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} group_id = self.identity_api.create_group(group['id'], group)['id'] self.identity_api.add_user_to_group(user_ref['id'], group_id) role_ref_list = [] for i in range(2): role_ref = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role_ref['id'], role_ref) role_ref_list.append(role_ref) self.assignment_api.add_role_to_user_and_project( user_id=user_ref['id'], tenant_id=project_ref['id'], role_id=role_ref['id']) role_list = self.assignment_api.get_roles_for_user_and_project( user_id=user_ref['id'], tenant_id=project_ref['id']) self.assertEqual(set(role_list), set([role_ref['id'] for role_ref in role_ref_list])) def test_get_role_by_user_and_project(self): roles_ref = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_bar['id']) self.assertNotIn(self.role_admin['id'], roles_ref) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], self.role_admin['id']) roles_ref = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_bar['id']) self.assertIn(self.role_admin['id'], roles_ref) self.assertNotIn('member', roles_ref) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], 'member') roles_ref = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_bar['id']) self.assertIn(self.role_admin['id'], roles_ref) self.assertIn('member', roles_ref) def test_get_roles_for_user_and_domain(self): """Test for getting roles for user on a domain. Test Plan: - Create a domain, with 2 users - Check no roles yet exit - Give user1 two roles on the domain, user2 one role - Get roles on user1 and the domain - maybe sure we only get back the 2 roles on user1 - Delete both roles from user1 - Check we get no roles back for user1 on domain """ new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) new_user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user1['id'], new_user1) new_user2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user2['id'], new_user2) roles_ref = self.assignment_api.list_grants( user_id=new_user1['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) # Now create the grants (roles are defined in default_fixtures) self.assignment_api.create_grant(user_id=new_user1['id'], domain_id=new_domain['id'], role_id='member') self.assignment_api.create_grant(user_id=new_user1['id'], domain_id=new_domain['id'], role_id='other') self.assignment_api.create_grant(user_id=new_user2['id'], domain_id=new_domain['id'], role_id='admin') # Read back the roles for user1 on domain roles_ids = self.assignment_api.get_roles_for_user_and_domain( new_user1['id'], new_domain['id']) self.assertEqual(len(roles_ids), 2) self.assertIn(self.role_member['id'], roles_ids) self.assertIn(self.role_other['id'], roles_ids) # Now delete both grants for user1 self.assignment_api.delete_grant(user_id=new_user1['id'], domain_id=new_domain['id'], role_id='member') self.assignment_api.delete_grant(user_id=new_user1['id'], domain_id=new_domain['id'], role_id='other') roles_ref = self.assignment_api.list_grants( user_id=new_user1['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) def test_get_roles_for_user_and_domain_404(self): """Test errors raised when getting roles for user on a domain. Test Plan: - Check non-existing user gives UserNotFound - Check non-existing domain gives DomainNotFound """ new_domain = self._get_domain_fixture() new_user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user1['id'], new_user1) self.assertRaises(exception.UserNotFound, self.assignment_api.get_roles_for_user_and_domain, uuid.uuid4().hex, new_domain['id']) self.assertRaises(exception.DomainNotFound, self.assignment_api.get_roles_for_user_and_domain, new_user1['id'], uuid.uuid4().hex) def test_get_roles_for_user_and_project_404(self): self.assertRaises(exception.UserNotFound, self.assignment_api.get_roles_for_user_and_project, uuid.uuid4().hex, self.tenant_bar['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_roles_for_user_and_project, self.user_foo['id'], uuid.uuid4().hex) def test_add_role_to_user_and_project_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.add_role_to_user_and_project, self.user_foo['id'], uuid.uuid4().hex, self.role_admin['id']) self.assertRaises(exception.RoleNotFound, self.assignment_api.add_role_to_user_and_project, self.user_foo['id'], self.tenant_bar['id'], uuid.uuid4().hex) def test_add_role_to_user_and_project_no_user(self): # If add_role_to_user_and_project and the user doesn't exist, then # no error. user_id_not_exist = uuid.uuid4().hex self.assignment_api.add_role_to_user_and_project( user_id_not_exist, self.tenant_bar['id'], self.role_admin['id']) def test_remove_role_from_user_and_project(self): self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], 'member') self.assignment_api.remove_role_from_user_and_project( self.user_foo['id'], self.tenant_bar['id'], 'member') roles_ref = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_bar['id']) self.assertNotIn('member', roles_ref) self.assertRaises(exception.NotFound, self.assignment_api. remove_role_from_user_and_project, self.user_foo['id'], self.tenant_bar['id'], 'member') def test_get_role_grant_by_user_and_project(self): roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_bar['id']) self.assertEqual(len(roles_ref), 1) self.assignment_api.create_grant(user_id=self.user_foo['id'], project_id=self.tenant_bar['id'], role_id=self.role_admin['id']) roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_bar['id']) self.assertIn(self.role_admin['id'], [role_ref['id'] for role_ref in roles_ref]) self.assignment_api.create_grant(user_id=self.user_foo['id'], project_id=self.tenant_bar['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_bar['id']) roles_ref_ids = [] for ref in roles_ref: roles_ref_ids.append(ref['id']) self.assertIn(self.role_admin['id'], roles_ref_ids) self.assertIn('member', roles_ref_ids) def test_remove_role_grant_from_user_and_project(self): self.assignment_api.create_grant(user_id=self.user_foo['id'], project_id=self.tenant_baz['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_baz['id']) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(user_id=self.user_foo['id'], project_id=self.tenant_baz['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=self.user_foo['id'], project_id=self.tenant_baz['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, user_id=self.user_foo['id'], project_id=self.tenant_baz['id'], role_id='member') def test_get_and_remove_role_grant_by_group_and_project(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': 'secret', 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], project_id=self.tenant_bar['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], project_id=self.tenant_bar['id']) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], project_id=self.tenant_bar['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, group_id=new_group['id'], project_id=self.tenant_bar['id'], role_id='member') def test_get_and_remove_role_grant_by_group_and_domain(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(group_id=new_group['id'], domain_id=new_domain['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], domain_id=new_domain['id']) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(group_id=new_group['id'], domain_id=new_domain['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, group_id=new_group['id'], domain_id=new_domain['id'], role_id='member') def test_get_and_remove_correct_role_grant_from_a_mix(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) new_project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': new_domain['id']} self.assignment_api.create_project(new_project['id'], new_project) new_group = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_group2 = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group2['id'], new_group2) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) new_user2 = {'id': uuid.uuid4().hex, 'name': 'new_user2', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user2['id'], new_user2) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) # First check we have no grants roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) # Now add the grant we are going to test for, and some others as # well just to make sure we get back the right one self.assignment_api.create_grant(group_id=new_group['id'], domain_id=new_domain['id'], role_id='member') self.assignment_api.create_grant(group_id=new_group2['id'], domain_id=new_domain['id'], role_id=self.role_admin['id']) self.assignment_api.create_grant(user_id=new_user2['id'], domain_id=new_domain['id'], role_id=self.role_admin['id']) self.assignment_api.create_grant(group_id=new_group['id'], project_id=new_project['id'], role_id=self.role_admin['id']) roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], domain_id=new_domain['id']) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(group_id=new_group['id'], domain_id=new_domain['id'], role_id='member') roles_ref = self.assignment_api.list_grants( group_id=new_group['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, group_id=new_group['id'], domain_id=new_domain['id'], role_id='member') def test_get_and_remove_role_grant_by_user_and_domain(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': 'secret', 'enabled': True, 'domain_id': new_domain['id']} self.identity_api.create_user(new_user['id'], new_user) roles_ref = self.assignment_api.list_grants( user_id=new_user['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(user_id=new_user['id'], domain_id=new_domain['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=new_user['id'], domain_id=new_domain['id']) self.assertDictEqual(roles_ref[0], self.role_member) self.assignment_api.delete_grant(user_id=new_user['id'], domain_id=new_domain['id'], role_id='member') roles_ref = self.assignment_api.list_grants( user_id=new_user['id'], domain_id=new_domain['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, user_id=new_user['id'], domain_id=new_domain['id'], role_id='member') def test_get_and_remove_role_grant_by_group_and_cross_domain(self): group1_domain1_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(group1_domain1_role['id'], group1_domain1_role) group1_domain2_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(group1_domain2_role['id'], group1_domain2_role) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) group1 = {'id': uuid.uuid4().hex, 'domain_id': domain1['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(group1['id'], group1) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 0) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain2['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=group1_domain1_role['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain2['id'], role_id=group1_domain2_role['id']) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain1['id']) self.assertDictEqual(roles_ref[0], group1_domain1_role) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain2['id']) self.assertDictEqual(roles_ref[0], group1_domain2_role) self.assignment_api.delete_grant(group_id=group1['id'], domain_id=domain2['id'], role_id=group1_domain2_role['id']) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain2['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, group_id=group1['id'], domain_id=domain2['id'], role_id=group1_domain2_role['id']) def test_get_and_remove_role_grant_by_user_and_cross_domain(self): user1_domain1_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(user1_domain1_role['id'], user1_domain1_role) user1_domain2_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(user1_domain2_role['id'], user1_domain2_role) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 0) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain2['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=user1_domain1_role['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain2['id'], role_id=user1_domain2_role['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain1['id']) self.assertDictEqual(roles_ref[0], user1_domain1_role) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain2['id']) self.assertDictEqual(roles_ref[0], user1_domain2_role) self.assignment_api.delete_grant(user_id=user1['id'], domain_id=domain2['id'], role_id=user1_domain2_role['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain2['id']) self.assertEqual(len(roles_ref), 0) self.assertRaises(exception.NotFound, self.assignment_api.delete_grant, user_id=user1['id'], domain_id=domain2['id'], role_id=user1_domain2_role['id']) def test_role_grant_by_group_and_cross_domain_project(self): role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role1['id'], role1) role2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role2['id'], role2) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain2['id']} self.assignment_api.create_project(project1['id'], project1) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role1['id']) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role2['id']) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], project_id=project1['id']) roles_ref_ids = [] for ref in roles_ref: roles_ref_ids.append(ref['id']) self.assertIn(role1['id'], roles_ref_ids) self.assertIn(role2['id'], roles_ref_ids) self.assignment_api.delete_grant(group_id=group1['id'], project_id=project1['id'], role_id=role1['id']) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 1) self.assertDictEqual(roles_ref[0], role2) def test_role_grant_by_user_and_cross_domain_project(self): role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role1['id'], role1) role2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role2['id'], role2) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain2['id']} self.assignment_api.create_project(project1['id'], project1) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role1['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role2['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) roles_ref_ids = [] for ref in roles_ref: roles_ref_ids.append(ref['id']) self.assertIn(role1['id'], roles_ref_ids) self.assertIn(role2['id'], roles_ref_ids) self.assignment_api.delete_grant(user_id=user1['id'], project_id=project1['id'], role_id=role1['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 1) self.assertDictEqual(roles_ref[0], role2) def test_delete_user_grant_no_user(self): # Can delete a grant where the user doesn't exist. role_id = uuid.uuid4().hex role = {'id': role_id, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role_id, role) user_id = uuid.uuid4().hex self.assignment_api.create_grant(role_id, user_id=user_id, project_id=self.tenant_bar['id']) self.assignment_api.delete_grant(role_id, user_id=user_id, project_id=self.tenant_bar['id']) def test_delete_group_grant_no_group(self): # Can delete a grant where the group doesn't exist. role_id = uuid.uuid4().hex role = {'id': role_id, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role_id, role) group_id = uuid.uuid4().hex self.assignment_api.create_grant(role_id, group_id=group_id, project_id=self.tenant_bar['id']) self.assignment_api.delete_grant(role_id, group_id=group_id, project_id=self.tenant_bar['id']) def test_multi_role_grant_by_user_group_on_project_domain(self): role_list = [] for _ in range(10): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group2['id'], group2) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) self.identity_api.add_user_to_group(user1['id'], group1['id']) self.identity_api.add_user_to_group(user1['id'], group2['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role_list[0]['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role_list[1]['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=role_list[2]['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=role_list[3]['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role_list[4]['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role_list[5]['id']) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role_list[6]['id']) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role_list[7]['id']) roles_ref = self.assignment_api.list_grants(user_id=user1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 2) self.assertIn(role_list[0], roles_ref) self.assertIn(role_list[1], roles_ref) roles_ref = self.assignment_api.list_grants(group_id=group1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 2) self.assertIn(role_list[2], roles_ref) self.assertIn(role_list[3], roles_ref) roles_ref = self.assignment_api.list_grants(user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 2) self.assertIn(role_list[4], roles_ref) self.assertIn(role_list[5], roles_ref) roles_ref = self.assignment_api.list_grants(group_id=group1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 2) self.assertIn(role_list[6], roles_ref) self.assertIn(role_list[7], roles_ref) # Now test the alternate way of getting back lists of grants, # where user and group roles are combined. These should match # the above results. combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(len(combined_list), 4) self.assertIn(role_list[4]['id'], combined_list) self.assertIn(role_list[5]['id'], combined_list) self.assertIn(role_list[6]['id'], combined_list) self.assertIn(role_list[7]['id'], combined_list) combined_role_list = self.assignment_api.get_roles_for_user_and_domain( user1['id'], domain1['id']) self.assertEqual(len(combined_role_list), 4) self.assertIn(role_list[0]['id'], combined_role_list) self.assertIn(role_list[1]['id'], combined_role_list) self.assertIn(role_list[2]['id'], combined_role_list) self.assertIn(role_list[3]['id'], combined_role_list) def test_multi_group_grants_on_project_domain(self): """Test multiple group roles for user on project and domain. Test Plan: - Create 6 roles - Create a domain, with a project, user and two groups - Make the user a member of both groups - Check no roles yet exit - Assign a role to each user and both groups on both the project and domain - Get a list of effective roles for the user on both the project and domain, checking we get back the correct three roles """ role_list = [] for _ in range(6): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group2['id'], group2) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) self.identity_api.add_user_to_group(user1['id'], group1['id']) self.identity_api.add_user_to_group(user1['id'], group2['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role_list[0]['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=role_list[1]['id']) self.assignment_api.create_grant(group_id=group2['id'], domain_id=domain1['id'], role_id=role_list[2]['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role_list[3]['id']) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role_list[4]['id']) self.assignment_api.create_grant(group_id=group2['id'], project_id=project1['id'], role_id=role_list[5]['id']) # Read by the roles, ensuring we get the correct 3 roles for # both project and domain combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(len(combined_list), 3) self.assertIn(role_list[3]['id'], combined_list) self.assertIn(role_list[4]['id'], combined_list) self.assertIn(role_list[5]['id'], combined_list) combined_role_list = self.assignment_api.get_roles_for_user_and_domain( user1['id'], domain1['id']) self.assertEqual(len(combined_role_list), 3) self.assertIn(role_list[0]['id'], combined_role_list) self.assertIn(role_list[1]['id'], combined_role_list) self.assertIn(role_list[2]['id'], combined_role_list) def test_delete_role_with_user_and_group_grants(self): role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role1['id'], role1) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role1['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role1['id']) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role1['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=role1['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 1) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 1) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 1) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 1) self.assignment_api.delete_role(role1['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 0) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 0) def test_delete_user_with_group_project_domain_links(self): role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role1['id'], role1) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role1['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role1['id']) self.identity_api.add_user_to_group(user_id=user1['id'], group_id=group1['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 1) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 1) self.identity_api.check_user_in_group( user_id=user1['id'], group_id=group1['id']) self.identity_api.delete_user(user1['id']) self.assertRaises(exception.NotFound, self.identity_api.check_user_in_group, user1['id'], group1['id']) def test_delete_group_with_user_project_domain_links(self): role1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role1['id'], role1) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=role1['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=role1['id']) self.identity_api.add_user_to_group(user_id=user1['id'], group_id=group1['id']) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 1) roles_ref = self.assignment_api.list_grants( group_id=group1['id'], domain_id=domain1['id']) self.assertEqual(len(roles_ref), 1) self.identity_api.check_user_in_group( user_id=user1['id'], group_id=group1['id']) self.identity_api.delete_group(group1['id']) self.identity_api.get_user(user1['id']) def test_delete_domain_with_user_group_project_links(self): #TODO(chungg):add test case once expected behaviour defined pass def test_role_crud(self): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_ref = self.assignment_api.get_role(role['id']) role_ref_dict = dict((x, role_ref[x]) for x in role_ref) self.assertDictEqual(role_ref_dict, role) role['name'] = uuid.uuid4().hex updated_role_ref = self.assignment_api.update_role(role['id'], role) role_ref = self.assignment_api.get_role(role['id']) role_ref_dict = dict((x, role_ref[x]) for x in role_ref) self.assertDictEqual(role_ref_dict, role) self.assertDictEqual(role_ref_dict, updated_role_ref) self.assignment_api.delete_role(role['id']) self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, role['id']) def test_update_role_404(self): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assertRaises(exception.RoleNotFound, self.assignment_api.update_role, role['id'], role) def test_add_user_to_project(self): self.assignment_api.add_user_to_project(self.tenant_baz['id'], self.user_foo['id']) tenants = self.assignment_api.list_projects_for_user( self.user_foo['id']) self.assertIn(self.tenant_baz, tenants) def test_add_user_to_project_missing_default_role(self): self.assignment_api.delete_role(CONF.member_role_id) self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, CONF.member_role_id) self.assignment_api.add_user_to_project(self.tenant_baz['id'], self.user_foo['id']) tenants = ( self.assignment_api.list_projects_for_user(self.user_foo['id'])) self.assertIn(self.tenant_baz, tenants) default_role = self.assignment_api.get_role(CONF.member_role_id) self.assertIsNotNone(default_role) def test_add_user_to_project_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.add_user_to_project, uuid.uuid4().hex, self.user_foo['id']) def test_add_user_to_project_no_user(self): # If add_user_to_project and the user doesn't exist, then # no error. user_id_not_exist = uuid.uuid4().hex self.assignment_api.add_user_to_project(self.tenant_bar['id'], user_id_not_exist) def test_remove_user_from_project(self): self.assignment_api.add_user_to_project(self.tenant_baz['id'], self.user_foo['id']) self.assignment_api.remove_user_from_project(self.tenant_baz['id'], self.user_foo['id']) tenants = self.assignment_api.list_projects_for_user( self.user_foo['id']) self.assertNotIn(self.tenant_baz, tenants) def test_remove_user_from_project_race_delete_role(self): self.assignment_api.add_user_to_project(self.tenant_baz['id'], self.user_foo['id']) self.assignment_api.add_role_to_user_and_project( tenant_id=self.tenant_baz['id'], user_id=self.user_foo['id'], role_id=self.role_other['id']) # Mock a race condition, delete a role after # get_roles_for_user_and_project() is called in # remove_user_from_project(). roles = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_baz['id']) self.assignment_api.delete_role(self.role_other['id']) self.assignment_api.get_roles_for_user_and_project = mock.Mock( return_value=roles) self.assignment_api.remove_user_from_project(self.tenant_baz['id'], self.user_foo['id']) tenants = self.assignment_api.list_projects_for_user( self.user_foo['id']) self.assertNotIn(self.tenant_baz, tenants) def test_remove_user_from_project_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.remove_user_from_project, uuid.uuid4().hex, self.user_foo['id']) self.assertRaises(exception.UserNotFound, self.assignment_api.remove_user_from_project, self.tenant_bar['id'], uuid.uuid4().hex) self.assertRaises(exception.NotFound, self.assignment_api.remove_user_from_project, self.tenant_baz['id'], self.user_foo['id']) def test_list_user_project_ids_404(self): self.assertRaises(exception.UserNotFound, self.assignment_api.list_projects_for_user, uuid.uuid4().hex) def test_update_project_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.update_project, uuid.uuid4().hex, dict()) def test_delete_project_404(self): self.assertRaises(exception.ProjectNotFound, self.assignment_api.delete_project, uuid.uuid4().hex) def test_update_user_404(self): user_id = uuid.uuid4().hex self.assertRaises(exception.UserNotFound, self.identity_api.update_user, user_id, {'id': user_id, 'domain_id': DEFAULT_DOMAIN_ID}) def test_delete_user_with_project_association(self): user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} self.identity_api.create_user(user['id'], user) self.assignment_api.add_user_to_project(self.tenant_bar['id'], user['id']) self.identity_api.delete_user(user['id']) self.assertRaises(exception.UserNotFound, self.assignment_api.list_projects_for_user, user['id']) def test_delete_user_with_project_roles(self): user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex} self.identity_api.create_user(user['id'], user) self.assignment_api.add_role_to_user_and_project( user['id'], self.tenant_bar['id'], self.role_member['id']) self.identity_api.delete_user(user['id']) self.assertRaises(exception.UserNotFound, self.assignment_api.list_projects_for_user, user['id']) def test_delete_user_404(self): self.assertRaises(exception.UserNotFound, self.identity_api.delete_user, uuid.uuid4().hex) def test_delete_role_404(self): self.assertRaises(exception.RoleNotFound, self.assignment_api.delete_role, uuid.uuid4().hex) def test_create_update_delete_unicode_project(self): unicode_project_name = u'name \u540d\u5b57' project = {'id': uuid.uuid4().hex, 'name': unicode_project_name, 'description': uuid.uuid4().hex, 'domain_id': CONF.identity.default_domain_id} self.assignment_api.create_project(project['id'], project) self.assignment_api.update_project(project['id'], project) self.assignment_api.delete_project(project['id']) def test_create_project_case_sensitivity(self): # create a ref with a lowercase name ref = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex.lower(), 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(ref['id'], ref) # assign a new ID with the same name, but this time in uppercase ref['id'] = uuid.uuid4().hex ref['name'] = ref['name'].upper() self.assignment_api.create_project(ref['id'], ref) def test_create_project_with_no_enabled_field(self): ref = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex.lower(), 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(ref['id'], ref) project = self.assignment_api.get_project(ref['id']) self.assertIs(project['enabled'], True) def test_create_project_long_name_fails(self): tenant = {'id': 'fake1', 'name': 'a' * 65, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.assignment_api.create_project, tenant['id'], tenant) def test_create_project_blank_name_fails(self): tenant = {'id': 'fake1', 'name': '', 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.assignment_api.create_project, tenant['id'], tenant) def test_create_project_invalid_name_fails(self): tenant = {'id': 'fake1', 'name': None, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.assignment_api.create_project, tenant['id'], tenant) tenant = {'id': 'fake1', 'name': 123, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.assignment_api.create_project, tenant['id'], tenant) def test_update_project_blank_name_fails(self): tenant = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant['name'] = '' self.assertRaises(exception.ValidationError, self.assignment_api.update_project, tenant['id'], tenant) def test_update_project_long_name_fails(self): tenant = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant['name'] = 'a' * 65 self.assertRaises(exception.ValidationError, self.assignment_api.update_project, tenant['id'], tenant) def test_update_project_invalid_name_fails(self): tenant = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant['name'] = None self.assertRaises(exception.ValidationError, self.assignment_api.update_project, tenant['id'], tenant) tenant['name'] = 123 self.assertRaises(exception.ValidationError, self.assignment_api.update_project, tenant['id'], tenant) def test_create_user_case_sensitivity(self): # create a ref with a lowercase name ref = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex.lower(), 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user(ref['id'], ref) # assign a new ID with the same name, but this time in uppercase ref['id'] = uuid.uuid4().hex ref['name'] = ref['name'].upper() self.identity_api.create_user(ref['id'], ref) def test_create_user_long_name_fails(self): user = {'id': 'fake1', 'name': 'a' * 256, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.identity_api.create_user, 'fake1', user) def test_create_user_blank_name_fails(self): user = {'id': 'fake1', 'name': '', 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.identity_api.create_user, 'fake1', user) def test_create_user_missed_password(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) self.identity_api.get_user('fake1') # Make sure the user is not allowed to login # with a password that is empty string or None self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id='fake1', password='') self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id='fake1', password=None) def test_create_user_none_password(self): user = {'id': 'fake1', 'name': 'fake1', 'password': None, 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) self.identity_api.get_user('fake1') # Make sure the user is not allowed to login # with a password that is empty string or None self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id='fake1', password='') self.assertRaises(AssertionError, self.identity_api.authenticate, context={}, user_id='fake1', password=None) def test_create_user_invalid_name_fails(self): user = {'id': 'fake1', 'name': None, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.identity_api.create_user, 'fake1', user) user = {'id': 'fake1', 'name': 123, 'domain_id': DEFAULT_DOMAIN_ID} self.assertRaises(exception.ValidationError, self.identity_api.create_user, 'fake1', user) def test_update_project_invalid_enabled_type_string(self): project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertEqual(project_ref['enabled'], True) # Strings are not valid boolean values project['enabled'] = "false" self.assertRaises(exception.ValidationError, self.assignment_api.update_project, project['id'], project) def test_create_project_invalid_enabled_type_string(self): project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, # invalid string value 'enabled': "true"} self.assertRaises(exception.ValidationError, self.assignment_api.create_project, project['id'], project) def test_create_user_invalid_enabled_type_string(self): user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'password': uuid.uuid4().hex, # invalid string value 'enabled': "true"} self.assertRaises(exception.ValidationError, self.identity_api.create_user, user['id'], user) def test_update_user_long_name_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) user['name'] = 'a' * 256 self.assertRaises(exception.ValidationError, self.identity_api.update_user, 'fake1', user) def test_update_user_blank_name_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) user['name'] = '' self.assertRaises(exception.ValidationError, self.identity_api.update_user, 'fake1', user) def test_update_user_invalid_name_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) user['name'] = None self.assertRaises(exception.ValidationError, self.identity_api.update_user, 'fake1', user) user['name'] = 123 self.assertRaises(exception.ValidationError, self.identity_api.update_user, 'fake1', user) def test_list_users(self): users = self.identity_api.list_users() self.assertEqual(len(default_fixtures.USERS), len(users)) user_ids = set(user['id'] for user in users) expected_user_ids = set(user['id'] for user in default_fixtures.USERS) for user_ref in users: self.assertNotIn('password', user_ref) self.assertEqual(expected_user_ids, user_ids) def test_list_groups(self): group1 = { 'id': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'name': uuid.uuid4().hex} group2 = { 'id': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'name': uuid.uuid4().hex} self.identity_api.create_group(group1['id'], group1) self.identity_api.create_group(group2['id'], group2) groups = self.identity_api.list_groups() self.assertEqual(len(groups), 2) group_ids = [] for group in groups: group_ids.append(group.get('id')) self.assertIn(group1['id'], group_ids) self.assertIn(group2['id'], group_ids) def test_list_domains(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) self.assignment_api.create_domain(domain2['id'], domain2) domains = self.assignment_api.list_domains() self.assertEqual(len(domains), 3) domain_ids = [] for domain in domains: domain_ids.append(domain.get('id')) self.assertIn(DEFAULT_DOMAIN_ID, domain_ids) self.assertIn(domain1['id'], domain_ids) self.assertIn(domain2['id'], domain_ids) def test_list_projects(self): projects = self.assignment_api.list_projects() self.assertEqual(len(projects), 4) project_ids = [] for project in projects: project_ids.append(project.get('id')) self.assertIn(self.tenant_bar['id'], project_ids) self.assertIn(self.tenant_baz['id'], project_ids) def test_list_projects_for_domain(self): project_ids = ([x['id'] for x in self.assignment_api.list_projects_in_domain( DEFAULT_DOMAIN_ID)]) self.assertEqual(len(project_ids), 4) self.assertIn(self.tenant_bar['id'], project_ids) self.assertIn(self.tenant_baz['id'], project_ids) self.assertIn(self.tenant_mtu['id'], project_ids) self.assertIn(self.tenant_service['id'], project_ids) def test_list_projects_for_alternate_domain(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project2['id'], project2) project_ids = ([x['id'] for x in self.assignment_api.list_projects_in_domain( domain1['id'])]) self.assertEqual(len(project_ids), 2) self.assertIn(project1['id'], project_ids) self.assertIn(project2['id'], project_ids) def test_list_roles(self): roles = self.assignment_api.list_roles() self.assertEqual(len(default_fixtures.ROLES), len(roles)) role_ids = set(role['id'] for role in roles) expected_role_ids = set(role['id'] for role in default_fixtures.ROLES) self.assertEqual(expected_role_ids, role_ids) def test_delete_project_with_role_assignments(self): tenant = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project(tenant['id'], tenant) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], tenant['id'], 'member') self.assignment_api.delete_project(tenant['id']) self.assertRaises(exception.NotFound, self.assignment_api.get_project, tenant['id']) def test_delete_role_check_role_grant(self): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} alt_role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) self.assignment_api.create_role(alt_role['id'], alt_role) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], role['id']) self.assignment_api.add_role_to_user_and_project( self.user_foo['id'], self.tenant_bar['id'], alt_role['id']) self.assignment_api.delete_role(role['id']) roles_ref = self.assignment_api.get_roles_for_user_and_project( self.user_foo['id'], self.tenant_bar['id']) self.assertNotIn(role['id'], roles_ref) self.assertIn(alt_role['id'], roles_ref) def test_create_project_doesnt_modify_passed_in_dict(self): new_project = {'id': 'tenant_id', 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} original_project = new_project.copy() self.assignment_api.create_project('tenant_id', new_project) self.assertDictEqual(original_project, new_project) def test_create_user_doesnt_modify_passed_in_dict(self): new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} original_user = new_user.copy() self.identity_api.create_user('user_id', new_user) self.assertDictEqual(original_user, new_user) def test_update_user_enable(self): user = {'id': 'fake1', 'name': 'fake1', 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], True) user['enabled'] = False self.identity_api.update_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], user['enabled']) # If not present, enabled field should not be updated del user['enabled'] self.identity_api.update_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], False) user['enabled'] = True self.identity_api.update_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], user['enabled']) del user['enabled'] self.identity_api.update_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], True) # Integers are valid Python's booleans. Explicitly test it. user['enabled'] = 0 self.identity_api.update_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], False) # Any integers other than 0 are interpreted as True user['enabled'] = -42 self.identity_api.update_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], True) def test_update_user_name(self): user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user(user['id'], user) user_ref = self.identity_api.get_user(user['id']) self.assertEqual(user['name'], user_ref['name']) changed_name = user_ref['name'] + '_changed' user_ref['name'] = changed_name updated_user = self.identity_api.update_user(user_ref['id'], user_ref) # NOTE(dstanek): the SQL backend adds an 'extra' field containing a # dictionary of the extra fields in addition to the # fields in the object. For the details see: # SqlIdentity.test_update_project_returns_extra updated_user.pop('extra', None) self.assertDictEqual(user_ref, updated_user) user_ref = self.identity_api.get_user(user_ref['id']) self.assertEqual(user_ref['name'], changed_name) def test_update_user_enable_fails(self): user = {'id': 'fake1', 'name': 'fake1', 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user('fake1', user) user_ref = self.identity_api.get_user('fake1') self.assertEqual(user_ref['enabled'], True) # Strings are not valid boolean values user['enabled'] = "false" self.assertRaises(exception.ValidationError, self.identity_api.update_user, 'fake1', user) def test_update_project_enable(self): tenant = {'id': 'fake1', 'name': 'fake1', 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID} self.assignment_api.create_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual(tenant_ref['enabled'], True) tenant['enabled'] = False self.assignment_api.update_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual(tenant_ref['enabled'], tenant['enabled']) # If not present, enabled field should not be updated del tenant['enabled'] self.assignment_api.update_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual(tenant_ref['enabled'], False) tenant['enabled'] = True self.assignment_api.update_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual(tenant_ref['enabled'], tenant['enabled']) del tenant['enabled'] self.assignment_api.update_project('fake1', tenant) tenant_ref = self.assignment_api.get_project('fake1') self.assertEqual(tenant_ref['enabled'], True) def test_add_user_to_group(self): domain = self._get_domain_fixture() new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) groups = self.identity_api.list_groups_for_user(new_user['id']) found = False for x in groups: if (x['id'] == new_group['id']): found = True self.assertTrue(found) def test_add_user_to_group_404(self): domain = self._get_domain_fixture() new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.assertRaises(exception.GroupNotFound, self.identity_api.add_user_to_group, new_user['id'], uuid.uuid4().hex) new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) self.assertRaises(exception.UserNotFound, self.identity_api.add_user_to_group, uuid.uuid4().hex, new_group['id']) def test_check_user_in_group(self): domain = self._get_domain_fixture() new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) self.identity_api.check_user_in_group(new_user['id'], new_group['id']) def test_create_invalid_domain_fails(self): new_group = {'id': uuid.uuid4().hex, 'domain_id': "doesnotexist", 'name': uuid.uuid4().hex} self.assertRaises(exception.DomainNotFound, self.identity_api.create_group, new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': "doesnotexist"} self.assertRaises(exception.DomainNotFound, self.identity_api.create_user, new_user['id'], new_user) def test_check_user_not_in_group(self): new_group = { 'id': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) self.assertRaises(exception.UserNotFound, self.identity_api.check_user_in_group, uuid.uuid4().hex, new_group['id']) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_user(new_user['id'], new_user) self.assertRaises(exception.NotFound, self.identity_api.check_user_in_group, new_user['id'], new_group['id']) def test_list_users_in_group(self): domain = self._get_domain_fixture() new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) # Make sure we get an empty list back on a new group, not an error. user_refs = self.identity_api.list_users_in_group(new_group['id']) self.assertEqual(user_refs, []) # Make sure we get the correct users back once they have been added # to the group. new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) user_refs = self.identity_api.list_users_in_group(new_group['id']) found = False for x in user_refs: if (x['id'] == new_user['id']): found = True self.assertNotIn('password', x) self.assertTrue(found) def test_list_groups_for_user(self): domain = self._get_domain_fixture() test_groups = [] test_users = [] GROUP_COUNT = 3 USER_COUNT = 2 for x in range(0, USER_COUNT): new_user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} test_users.append(new_user) self.identity_api.create_user(new_user['id'], new_user) positive_user = test_users[0] negative_user = test_users[1] for x in range(0, USER_COUNT): group_refs = self.identity_api.list_groups_for_user( test_users[x]['id']) self.assertEqual(len(group_refs), 0) for x in range(0, GROUP_COUNT): before_count = x after_count = x + 1 new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) test_groups.append(new_group) #add the user to the group and ensure that the #group count increases by one for each group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), before_count) self.identity_api.add_user_to_group( positive_user['id'], new_group['id']) group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), after_count) #Make sure the group count for the unrelated user #did not change group_refs = self.identity_api.list_groups_for_user( negative_user['id']) self.assertEqual(len(group_refs), 0) #remove the user from each group and ensure that #the group count reduces by one for each for x in range(0, 3): before_count = GROUP_COUNT - x after_count = GROUP_COUNT - x - 1 group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), before_count) self.identity_api.remove_user_from_group( positive_user['id'], test_groups[x]['id']) group_refs = self.identity_api.list_groups_for_user( positive_user['id']) self.assertEqual(len(group_refs), after_count) #Make sure the group count for the unrelated user #did not change group_refs = self.identity_api.list_groups_for_user( negative_user['id']) self.assertEqual(len(group_refs), 0) def test_remove_user_from_group(self): domain = self._get_domain_fixture() new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) self.identity_api.add_user_to_group(new_user['id'], new_group['id']) groups = self.identity_api.list_groups_for_user(new_user['id']) self.assertIn(new_group['id'], [x['id'] for x in groups]) self.identity_api.remove_user_from_group(new_user['id'], new_group['id']) groups = self.identity_api.list_groups_for_user(new_user['id']) self.assertNotIn(new_group['id'], [x['id'] for x in groups]) def test_remove_user_from_group_404(self): domain = self._get_domain_fixture() new_user = {'id': uuid.uuid4().hex, 'name': 'new_user', 'password': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain['id']} self.identity_api.create_user(new_user['id'], new_user) new_group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(new_group['id'], new_group) self.assertRaises(exception.NotFound, self.identity_api.remove_user_from_group, new_user['id'], uuid.uuid4().hex) self.assertRaises(exception.NotFound, self.identity_api.remove_user_from_group, uuid.uuid4().hex, new_group['id']) self.assertRaises(exception.NotFound, self.identity_api.remove_user_from_group, uuid.uuid4().hex, uuid.uuid4().hex) def test_group_crud(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain['id'], domain) group = {'id': uuid.uuid4().hex, 'domain_id': domain['id'], 'name': uuid.uuid4().hex} self.identity_api.create_group(group['id'], group) group_ref = self.identity_api.get_group(group['id']) self.assertDictContainsSubset(group, group_ref) group['name'] = uuid.uuid4().hex self.identity_api.update_group(group['id'], group) group_ref = self.identity_api.get_group(group['id']) self.assertDictContainsSubset(group, group_ref) self.identity_api.delete_group(group['id']) self.assertRaises(exception.GroupNotFound, self.identity_api.get_group, group['id']) def test_create_duplicate_group_name_fails(self): group1 = {'id': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'name': uuid.uuid4().hex} group2 = {'id': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'name': group1['name']} self.identity_api.create_group(group1['id'], group1) self.assertRaises(exception.Conflict, self.identity_api.create_group, group2['id'], group2) def test_create_duplicate_group_name_in_different_domains(self): new_domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(new_domain['id'], new_domain) group1 = {'id': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'name': uuid.uuid4().hex} group2 = {'id': uuid.uuid4().hex, 'domain_id': new_domain['id'], 'name': group1['name']} self.identity_api.create_group(group1['id'], group1) self.identity_api.create_group(group2['id'], group2) def test_move_group_between_domains(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) group = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.identity_api.create_group(group['id'], group) group['domain_id'] = domain2['id'] self.identity_api.update_group(group['id'], group) def test_move_group_between_domains_with_clashing_names_fails(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) # First, create a group in domain1 group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.identity_api.create_group(group1['id'], group1) # Now create a group in domain2 with a potentially clashing # name - which should work since we have domain separation group2 = {'id': uuid.uuid4().hex, 'name': group1['name'], 'domain_id': domain2['id']} self.identity_api.create_group(group2['id'], group2) # Now try and move group1 into the 2nd domain - which should # fail since the names clash group1['domain_id'] = domain2['id'] self.assertRaises(exception.Conflict, self.identity_api.update_group, group1['id'], group1) def test_project_crud(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} self.assignment_api.create_domain(domain['id'], domain) project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictContainsSubset(project, project_ref) project['name'] = uuid.uuid4().hex self.assignment_api.update_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictContainsSubset(project, project_ref) self.assignment_api.delete_project(project['id']) self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project['id']) def test_project_update_missing_attrs_with_a_value(self): # Creating a project with no description attribute. project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'enabled': True} self.assignment_api.create_project(project['id'], project) # Add a description attribute. project['description'] = uuid.uuid4().hex self.assignment_api.update_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictEqual(project_ref, project) def test_project_update_missing_attrs_with_a_falsey_value(self): # Creating a project with no description attribute. project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'enabled': True} self.assignment_api.create_project(project['id'], project) # Add a description attribute. project['description'] = '' self.assignment_api.update_project(project['id'], project) project_ref = self.assignment_api.get_project(project['id']) self.assertDictEqual(project_ref, project) def test_domain_crud(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} self.assignment_api.create_domain(domain['id'], domain) domain_ref = self.assignment_api.get_domain(domain['id']) self.assertDictEqual(domain_ref, domain) domain['name'] = uuid.uuid4().hex self.assignment_api.update_domain(domain['id'], domain) domain_ref = self.assignment_api.get_domain(domain['id']) self.assertDictEqual(domain_ref, domain) # Ensure an 'enabled' domain cannot be deleted self.assertRaises(exception.ForbiddenAction, self.assignment_api.delete_domain, domain_id=domain['id']) # Disable the domain domain['enabled'] = False self.assignment_api.update_domain(domain['id'], domain) # Delete the domain self.assignment_api.delete_domain(domain['id']) # Make sure the domain no longer exists self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, domain['id']) def test_create_domain_case_sensitivity(self): # create a ref with a lowercase name ref = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex.lower()} self.assignment_api.create_domain(ref['id'], ref) # assign a new ID with the same name, but this time in uppercase ref['id'] = uuid.uuid4().hex ref['name'] = ref['name'].upper() self.assignment_api.create_domain(ref['id'], ref) def test_attribute_update(self): project = { 'domain_id': DEFAULT_DOMAIN_ID, 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_project(project['id'], project) # pick a key known to be non-existent key = 'description' def assert_key_equals(value): project_ref = self.assignment_api.update_project( project['id'], project) self.assertEqual(project_ref[key], value) project_ref = self.assignment_api.get_project(project['id']) self.assertEqual(project_ref[key], value) def assert_get_key_is(value): project_ref = self.assignment_api.update_project( project['id'], project) self.assertIs(project_ref.get(key), value) project_ref = self.assignment_api.get_project(project['id']) self.assertIs(project_ref.get(key), value) # add an attribute that doesn't exist, set it to a falsey value value = '' project[key] = value assert_key_equals(value) # set an attribute with a falsey value to null value = None project[key] = value assert_get_key_is(value) # do it again, in case updating from this situation is handled oddly value = None project[key] = value assert_get_key_is(value) # set a possibly-null value to a falsey value value = '' project[key] = value assert_key_equals(value) # set a falsey value to a truthy value value = uuid.uuid4().hex project[key] = value assert_key_equals(value) def test_user_crud(self): user = {'domain_id': DEFAULT_DOMAIN_ID, 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': 'passw0rd'} self.identity_api.create_user(user['id'], user) user_ref = self.identity_api.get_user(user['id']) del user['password'] user_ref_dict = dict((x, user_ref[x]) for x in user_ref) self.assertDictContainsSubset(user, user_ref_dict) user['password'] = uuid.uuid4().hex self.identity_api.update_user(user['id'], user) user_ref = self.identity_api.get_user(user['id']) del user['password'] user_ref_dict = dict((x, user_ref[x]) for x in user_ref) self.assertDictContainsSubset(user, user_ref_dict) self.identity_api.delete_user(user['id']) self.assertRaises(exception.UserNotFound, self.identity_api.get_user, user['id']) def test_list_projects_for_user(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain['id'], domain) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': domain['id'], 'enabled': True} self.identity_api.create_user(user1['id'], user1) user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(len(user_projects), 0) self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_bar['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_baz['id'], role_id=self.role_member['id']) user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(len(user_projects), 2) def test_list_projects_for_user_with_grants(self): # Create two groups each with a role on a different project, and # make user1 a member of both groups. Both these new projects # should now be included, along with any direct user grants. domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain['id'], domain) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': domain['id'], 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.identity_api.create_group(group1['id'], group1) group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.identity_api.create_group(group2['id'], group2) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project1['id'], project1) project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project2['id'], project2) self.identity_api.add_user_to_group(user1['id'], group1['id']) self.identity_api.add_user_to_group(user1['id'], group2['id']) # Create 3 grants, one user grant, the other two as group grants self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_bar['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(group_id=group1['id'], project_id=project1['id'], role_id=self.role_admin['id']) self.assignment_api.create_grant(group_id=group2['id'], project_id=project2['id'], role_id=self.role_admin['id']) user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(len(user_projects), 3) @tests.skip_if_cache_disabled('assignment') def test_cache_layer_domain_crud(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} domain_id = domain['id'] # Create Domain self.assignment_api.create_domain(domain_id, domain) domain_ref = self.assignment_api.get_domain(domain_id) updated_domain_ref = copy.deepcopy(domain_ref) updated_domain_ref['name'] = uuid.uuid4().hex # Update domain, bypassing assignment api manager self.assignment_api.driver.update_domain(domain_id, updated_domain_ref) # Verify get_domain still returns the domain self.assertDictContainsSubset( domain_ref, self.assignment_api.get_domain(domain_id)) # Invalidate cache self.assignment_api.get_domain.invalidate(self.assignment_api, domain_id) # Verify get_domain returns the updated domain self.assertDictContainsSubset( updated_domain_ref, self.assignment_api.get_domain(domain_id)) # Update the domain back to original ref, using the assignment api # manager self.assignment_api.update_domain(domain_id, domain_ref) self.assertDictContainsSubset( domain_ref, self.assignment_api.get_domain(domain_id)) # Make sure domain is 'disabled', bypass assignment api manager domain_ref_disabled = domain_ref.copy() domain_ref_disabled['enabled'] = False self.assignment_api.driver.update_domain(domain_id, domain_ref_disabled) # Delete domain, bypassing assignment api manager self.assignment_api.driver.delete_domain(domain_id) # Verify get_domain still returns the domain self.assertDictContainsSubset( domain_ref, self.assignment_api.get_domain(domain_id)) # Invalidate cache self.assignment_api.get_domain.invalidate(self.assignment_api, domain_id) # Verify get_domain now raises DomainNotFound self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, domain_id) # Recreate Domain self.assignment_api.create_domain(domain_id, domain) self.assignment_api.get_domain(domain_id) # Make sure domain is 'disabled', bypass assignment api manager domain['enabled'] = False self.assignment_api.driver.update_domain(domain_id, domain) # Delete domain self.assignment_api.delete_domain(domain_id) # verify DomainNotFound raised self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain, domain_id) @tests.skip_if_cache_disabled('assignment') def test_cache_layer_project_crud(self): domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'enabled': True} project = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} project_id = project['id'] self.assignment_api.create_domain(domain['id'], domain) # Create a project self.assignment_api.create_project(project_id, project) self.assignment_api.get_project(project_id) updated_project = copy.deepcopy(project) updated_project['name'] = uuid.uuid4().hex # Update project, bypassing assignment_api manager self.assignment_api.driver.update_project(project_id, updated_project) # Verify get_project still returns the original project_ref self.assertDictContainsSubset( project, self.assignment_api.get_project(project_id)) # Invalidate cache self.assignment_api.get_project.invalidate(self.assignment_api, project_id) # Verify get_project now returns the new project self.assertDictContainsSubset( updated_project, self.assignment_api.get_project(project_id)) # Update project using the assignment_api manager back to original self.assignment_api.update_project(project['id'], project) # Verify get_project returns the original project_ref self.assertDictContainsSubset( project, self.assignment_api.get_project(project_id)) # Delete project bypassing assignment_api self.assignment_api.driver.delete_project(project_id) # Verify get_project still returns the project_ref self.assertDictContainsSubset( project, self.assignment_api.get_project(project_id)) # Invalidate cache self.assignment_api.get_project.invalidate(self.assignment_api, project_id) # Verify ProjectNotFound now raised self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project_id) # recreate project self.assignment_api.create_project(project_id, project) self.assignment_api.get_project(project_id) # delete project self.assignment_api.delete_project(project_id) # Verify ProjectNotFound is raised self.assertRaises(exception.ProjectNotFound, self.assignment_api.get_project, project_id) @tests.skip_if_cache_disabled('assignment') def test_cache_layer_role_crud(self): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} role_id = role['id'] # Create role self.assignment_api.create_role(role_id, role) role_ref = self.assignment_api.get_role(role_id) updated_role_ref = copy.deepcopy(role_ref) updated_role_ref['name'] = uuid.uuid4().hex # Update role, bypassing the assignment api manager self.assignment_api.driver.update_role(role_id, updated_role_ref) # Verify get_role still returns old ref self.assertDictEqual(role_ref, self.assignment_api.get_role(role_id)) # Invalidate Cache self.assignment_api.get_role.invalidate(self.assignment_api, role_id) # Verify get_role returns the new role_ref self.assertDictEqual(updated_role_ref, self.assignment_api.get_role(role_id)) # Update role back to original via the assignment api manager self.assignment_api.update_role(role_id, role_ref) # Verify get_role returns the original role ref self.assertDictEqual(role_ref, self.assignment_api.get_role(role_id)) # Delete role bypassing the assignment api manager self.assignment_api.driver.delete_role(role_id) # Verify get_role still returns the role_ref self.assertDictEqual(role_ref, self.assignment_api.get_role(role_id)) # Invalidate cache self.assignment_api.get_role.invalidate(self.assignment_api, role_id) # Verify RoleNotFound is now raised self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, role_id) # recreate role self.assignment_api.create_role(role_id, role) self.assignment_api.get_role(role_id) # delete role via the assignment api manager self.assignment_api.delete_role(role_id) # verity RoleNotFound is now raised self.assertRaises(exception.RoleNotFound, self.assignment_api.get_role, role_id) def create_user_dict(self, **attributes): user_dict = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'enabled': True} user_dict.update(attributes) return user_dict def test_arbitrary_attributes_are_returned_from_create_user(self): attr_value = uuid.uuid4().hex user_data = self.create_user_dict(arbitrary_attr=attr_value) user = self.identity_api.create_user(user_data['id'], user_data) self.assertEqual(user['arbitrary_attr'], attr_value) def test_arbitrary_attributes_are_returned_from_get_user(self): attr_value = uuid.uuid4().hex user_data = self.create_user_dict(arbitrary_attr=attr_value) self.identity_api.create_user(user_data['id'], user_data) user = self.identity_api.get_user(user_data['id']) self.assertEqual(user['arbitrary_attr'], attr_value) def test_new_arbitrary_attributes_are_returned_from_update_user(self): user_data = self.create_user_dict() user = self.identity_api.create_user(user_data['id'], user_data) attr_value = uuid.uuid4().hex user['arbitrary_attr'] = attr_value updated_user = self.identity_api.update_user(user['id'], user) self.assertEqual(updated_user['arbitrary_attr'], attr_value) def test_updated_arbitrary_attributes_are_returned_from_update_user(self): attr_value = uuid.uuid4().hex user_data = self.create_user_dict(arbitrary_attr=attr_value) new_attr_value = uuid.uuid4().hex user = self.identity_api.create_user(user_data['id'], user_data) user['arbitrary_attr'] = new_attr_value updated_user = self.identity_api.update_user(user['id'], user) self.assertEqual(updated_user['arbitrary_attr'], new_attr_value) def test_create_grant_no_user(self): # If call create_grant with a user that doesn't exist, doesn't fail. self.assignment_api.create_grant( self.role_other['id'], user_id=uuid.uuid4().hex, project_id=self.tenant_bar['id']) def test_create_grant_no_group(self): # If call create_grant with a group that doesn't exist, doesn't fail. self.assignment_api.create_grant( self.role_other['id'], group_id=uuid.uuid4().hex, project_id=self.tenant_bar['id']) def test_get_default_domain_by_name(self): domain_name = 'default' domain = {'id': uuid.uuid4().hex, 'name': domain_name, 'enabled': True} self.assignment_api.create_domain(domain['id'], domain) domain_ref = self.assignment_api.get_domain_by_name(domain_name) self.assertEqual(domain_ref, domain) def test_get_not_default_domain_by_name(self): domain_name = 'foo' self.assertRaises(exception.DomainNotFound, self.assignment_api.get_domain_by_name, domain_name) class TokenTests(object): def _create_token_id(self): # Token must start with MII here otherwise it fails the asn1 test # and is not hashed in a SQL backend. token_id = "MII" for i in range(1, 20): token_id += uuid.uuid4().hex return token_id def test_token_crud(self): token_id = self._create_token_id() data = {'id': token_id, 'a': 'b', 'trust_id': None, 'user': {'id': 'testuserid'}} data_ref = self.token_api.create_token(token_id, data) expires = data_ref.pop('expires') data_ref.pop('user_id') self.assertIsInstance(expires, datetime.datetime) data_ref.pop('id') data.pop('id') self.assertDictEqual(data_ref, data) new_data_ref = self.token_api.get_token(token_id) expires = new_data_ref.pop('expires') self.assertIsInstance(expires, datetime.datetime) new_data_ref.pop('user_id') new_data_ref.pop('id') self.assertEqual(new_data_ref, data) self.token_api.delete_token(token_id) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id) self.assertRaises(exception.TokenNotFound, self.token_api.delete_token, token_id) def create_token_sample_data(self, token_id=None, tenant_id=None, trust_id=None, user_id=None, expires=None): if token_id is None: token_id = self._create_token_id() if user_id is None: user_id = 'testuserid' # FIXME(morganfainberg): These tokens look nothing like "Real" tokens. # This should be updated when token_api is updated to merge in the # issue_token logic from the providers (token issuance should be a # pipeline). The fix should be in implementation of blueprint: # token-issuance-pipeline data = {'id': token_id, 'a': 'b', 'user': {'id': user_id}} if tenant_id is not None: data['tenant'] = {'id': tenant_id, 'name': tenant_id} if tenant_id is NULL_OBJECT: data['tenant'] = None if expires is not None: data['expires'] = expires if trust_id is not None: data['trust_id'] = trust_id data.setdefault('access', {}).setdefault('trust', {}) # Testuserid2 is used here since a trustee will be different in # the cases of impersonation and therefore should not match the # token's user_id. data['access']['trust']['trustee_user_id'] = 'testuserid2' data['token_version'] = provider.V2 # Issue token stores a copy of all token data at token['token_data']. # This emulates that assumption as part of the test. data['token_data'] = copy.deepcopy(data) new_token = self.token_api.create_token(token_id, data) return new_token['id'], data def test_delete_tokens(self): tokens = self.token_api._list_tokens('testuserid') self.assertEqual(len(tokens), 0) token_id1, data = self.create_token_sample_data( tenant_id='testtenantid') token_id2, data = self.create_token_sample_data( tenant_id='testtenantid') token_id3, data = self.create_token_sample_data( tenant_id='testtenantid', user_id='testuserid1') tokens = self.token_api._list_tokens('testuserid') self.assertEqual(len(tokens), 2) self.assertIn(token_id2, tokens) self.assertIn(token_id1, tokens) self.token_api.delete_tokens(user_id='testuserid', tenant_id='testtenantid') tokens = self.token_api._list_tokens('testuserid') self.assertEqual(len(tokens), 0) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id1) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id2) self.token_api.get_token(token_id3) def test_delete_tokens_trust(self): tokens = self.token_api._list_tokens(user_id='testuserid') self.assertEqual(len(tokens), 0) token_id1, data = self.create_token_sample_data( tenant_id='testtenantid', trust_id='testtrustid') token_id2, data = self.create_token_sample_data( tenant_id='testtenantid', user_id='testuserid1', trust_id='testtrustid1') tokens = self.token_api._list_tokens('testuserid') self.assertEqual(len(tokens), 1) self.assertIn(token_id1, tokens) self.token_api.delete_tokens(user_id='testuserid', tenant_id='testtenantid', trust_id='testtrustid') self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id1) self.token_api.get_token(token_id2) def _test_token_list(self, token_list_fn): tokens = token_list_fn('testuserid') self.assertEqual(len(tokens), 0) token_id1, data = self.create_token_sample_data() tokens = token_list_fn('testuserid') self.assertEqual(len(tokens), 1) self.assertIn(token_id1, tokens) token_id2, data = self.create_token_sample_data() tokens = token_list_fn('testuserid') self.assertEqual(len(tokens), 2) self.assertIn(token_id2, tokens) self.assertIn(token_id1, tokens) self.token_api.delete_token(token_id1) tokens = token_list_fn('testuserid') self.assertIn(token_id2, tokens) self.assertNotIn(token_id1, tokens) self.token_api.delete_token(token_id2) tokens = token_list_fn('testuserid') self.assertNotIn(token_id2, tokens) self.assertNotIn(token_id1, tokens) # tenant-specific tokens tenant1 = uuid.uuid4().hex tenant2 = uuid.uuid4().hex token_id3, data = self.create_token_sample_data(tenant_id=tenant1) token_id4, data = self.create_token_sample_data(tenant_id=tenant2) # test for existing but empty tenant (LP:1078497) token_id5, data = self.create_token_sample_data(tenant_id=NULL_OBJECT) tokens = token_list_fn('testuserid') self.assertEqual(len(tokens), 3) self.assertNotIn(token_id1, tokens) self.assertNotIn(token_id2, tokens) self.assertIn(token_id3, tokens) self.assertIn(token_id4, tokens) self.assertIn(token_id5, tokens) tokens = token_list_fn('testuserid', tenant2) self.assertEqual(len(tokens), 1) self.assertNotIn(token_id1, tokens) self.assertNotIn(token_id2, tokens) self.assertNotIn(token_id3, tokens) self.assertIn(token_id4, tokens) def test_token_list(self): self._test_token_list(self.token_api._list_tokens) def test_token_list_deprecated_public_interface(self): # TODO(morganfainberg): Remove once token_api.list_tokens is removed # (post Icehouse release) self._test_token_list(self.token_api.list_tokens) def test_token_list_trust(self): trust_id = uuid.uuid4().hex token_id5, data = self.create_token_sample_data(trust_id=trust_id) tokens = self.token_api._list_tokens('testuserid', trust_id=trust_id) self.assertEqual(len(tokens), 1) self.assertIn(token_id5, tokens) def test_get_token_404(self): self.assertRaises(exception.TokenNotFound, self.token_api.get_token, uuid.uuid4().hex) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, None) def test_delete_token_404(self): self.assertRaises(exception.TokenNotFound, self.token_api.delete_token, uuid.uuid4().hex) def test_expired_token(self): token_id = uuid.uuid4().hex expire_time = timeutils.utcnow() - datetime.timedelta(minutes=1) data = {'id_hash': token_id, 'id': token_id, 'a': 'b', 'expires': expire_time, 'trust_id': None, 'user': {'id': 'testuserid'}} data_ref = self.token_api.create_token(token_id, data) data_ref.pop('user_id') self.assertDictEqual(data_ref, data) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id) def test_null_expires_token(self): token_id = uuid.uuid4().hex data = {'id': token_id, 'id_hash': token_id, 'a': 'b', 'expires': None, 'user': {'id': 'testuserid'}} data_ref = self.token_api.create_token(token_id, data) self.assertIsNotNone(data_ref['expires']) new_data_ref = self.token_api.get_token(token_id) # MySQL doesn't store microseconds, so discard them before testing data_ref['expires'] = data_ref['expires'].replace(microsecond=0) new_data_ref['expires'] = new_data_ref['expires'].replace( microsecond=0) self.assertEqual(data_ref, new_data_ref) def check_list_revoked_tokens(self, token_ids): revoked_ids = [x['id'] for x in self.token_api.list_revoked_tokens()] for token_id in token_ids: self.assertIn(token_id, revoked_ids) def delete_token(self): token_id = uuid.uuid4().hex data = {'id_hash': token_id, 'id': token_id, 'a': 'b', 'user': {'id': 'testuserid'}} data_ref = self.token_api.create_token(token_id, data) self.token_api.delete_token(token_id) self.assertRaises( exception.TokenNotFound, self.token_api.get_token, data_ref['id']) self.assertRaises( exception.TokenNotFound, self.token_api.delete_token, data_ref['id']) return token_id def test_list_revoked_tokens_returns_empty_list(self): revoked_ids = [x['id'] for x in self.token_api.list_revoked_tokens()] self.assertEqual(revoked_ids, []) def test_list_revoked_tokens_for_single_token(self): self.check_list_revoked_tokens([self.delete_token()]) def test_list_revoked_tokens_for_multiple_tokens(self): self.check_list_revoked_tokens([self.delete_token() for x in six.moves.range(2)]) def test_flush_expired_token(self): token_id = uuid.uuid4().hex expire_time = timeutils.utcnow() - datetime.timedelta(minutes=1) data = {'id_hash': token_id, 'id': token_id, 'a': 'b', 'expires': expire_time, 'trust_id': None, 'user': {'id': 'testuserid'}} data_ref = self.token_api.create_token(token_id, data) data_ref.pop('user_id') self.assertDictEqual(data_ref, data) token_id = uuid.uuid4().hex expire_time = timeutils.utcnow() + datetime.timedelta(minutes=1) data = {'id_hash': token_id, 'id': token_id, 'a': 'b', 'expires': expire_time, 'trust_id': None, 'user': {'id': 'testuserid'}} data_ref = self.token_api.create_token(token_id, data) data_ref.pop('user_id') self.assertDictEqual(data_ref, data) self.token_api.flush_expired_tokens() tokens = self.token_api._list_tokens('testuserid') self.assertEqual(len(tokens), 1) self.assertIn(token_id, tokens) @tests.skip_if_cache_disabled('token') def test_revocation_list_cache(self): expire_time = timeutils.utcnow() + datetime.timedelta(minutes=10) token_id = uuid.uuid4().hex token_data = {'id_hash': token_id, 'id': token_id, 'a': 'b', 'expires': expire_time, 'trust_id': None, 'user': {'id': 'testuserid'}} token2_id = uuid.uuid4().hex token2_data = {'id_hash': token2_id, 'id': token2_id, 'a': 'b', 'expires': expire_time, 'trust_id': None, 'user': {'id': 'testuserid'}} # Create 2 Tokens. self.token_api.create_token(token_id, token_data) self.token_api.create_token(token2_id, token2_data) # Verify the revocation list is empty. self.assertEqual([], self.token_api.list_revoked_tokens()) # Delete a token directly, bypassing the manager. self.token_api.driver.delete_token(token_id) # Verify the revocation list is still empty. self.assertEqual([], self.token_api.list_revoked_tokens()) # Invalidate the revocation list. self.token_api.invalidate_revocation_list() # Verify the deleted token is in the revocation list. revoked_tokens = [x['id'] for x in self.token_api.list_revoked_tokens()] self.assertIn(token_id, revoked_tokens) # Delete the second token, through the manager self.token_api.delete_token(token2_id) revoked_tokens = [x['id'] for x in self.token_api.list_revoked_tokens()] # Verify both tokens are in the revocation list. self.assertIn(token_id, revoked_tokens) self.assertIn(token2_id, revoked_tokens) def test_predictable_revoked_pki_token_id(self): token_id = self._create_token_id() token_id_hash = hashlib.md5(token_id).hexdigest() token = {'user': {'id': uuid.uuid4().hex}} self.token_api.create_token(token_id, token) self.token_api.delete_token(token_id) revoked_ids = [x['id'] for x in self.token_api.list_revoked_tokens()] self.assertIn(token_id_hash, revoked_ids) self.assertNotIn(token_id, revoked_ids) for t in self.token_api.list_revoked_tokens(): self.assertIn('expires', t) def test_predictable_revoked_uuid_token_id(self): token_id = uuid.uuid4().hex token = {'user': {'id': uuid.uuid4().hex}} self.token_api.create_token(token_id, token) self.token_api.delete_token(token_id) revoked_ids = [x['id'] for x in self.token_api.list_revoked_tokens()] self.assertIn(token_id, revoked_ids) for t in self.token_api.list_revoked_tokens(): self.assertIn('expires', t) def test_create_unicode_token_id(self): token_id = six.text_type(self._create_token_id()) self.create_token_sample_data(token_id=token_id) self.token_api.get_token(token_id) def test_create_unicode_user_id(self): user_id = six.text_type(uuid.uuid4().hex) token_id, data = self.create_token_sample_data(user_id=user_id) self.token_api.get_token(token_id) def test_list_tokens_unicode_user_id(self): user_id = six.text_type(uuid.uuid4().hex) self.token_api.list_tokens(user_id) def test_token_expire_timezone(self): @test_utils.timezone def _create_token(expire_time): token_id = uuid.uuid4().hex user_id = six.text_type(uuid.uuid4().hex) return self.create_token_sample_data(token_id=token_id, user_id=user_id, expires=expire_time) for d in ['+0', '-11', '-8', '-5', '+5', '+8', '+14']: test_utils.TZ = 'UTC' + d expire_time = timeutils.utcnow() + datetime.timedelta(minutes=1) token_id, data_in = _create_token(expire_time) data_get = self.token_api.get_token(token_id) self.assertEqual(data_in['id'], data_get['id'], 'TZ=%s' % test_utils.TZ) expire_time_expired = ( timeutils.utcnow() + datetime.timedelta(minutes=-1)) token_id, data_in = _create_token(expire_time_expired) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, data_in['id']) class TokenCacheInvalidation(object): def _create_test_data(self): self.user = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'enabled': True} self.tenant = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID, 'enabled': True} # Create an equivalent of a scoped token token_dict = {'user': self.user, 'tenant': self.tenant, 'metadata': {}, 'id': 'placeholder'} token_id, data = self.token_provider_api.issue_v2_token(token_dict) self.scoped_token_id = token_id # ..and an un-scoped one token_dict = {'user': self.user, 'tenant': None, 'metadata': {}, 'id': 'placeholder'} token_id, data = self.token_provider_api.issue_v2_token(token_dict) self.unscoped_token_id = token_id # Validate them, in the various ways possible - this will load the # responses into the token cache. self._check_scoped_tokens_are_valid() self._check_unscoped_tokens_are_valid() def _check_unscoped_tokens_are_invalid(self): self.assertRaises( exception.TokenNotFound, self.token_provider_api.validate_token, self.unscoped_token_id) self.assertRaises( exception.TokenNotFound, self.token_provider_api.validate_v2_token, self.unscoped_token_id) def _check_scoped_tokens_are_invalid(self): self.assertRaises( exception.TokenNotFound, self.token_provider_api.validate_token, self.scoped_token_id) self.assertRaises( exception.TokenNotFound, self.token_provider_api.validate_token, self.scoped_token_id, self.tenant['id']) self.assertRaises( exception.TokenNotFound, self.token_provider_api.validate_v2_token, self.scoped_token_id) self.assertRaises( exception.TokenNotFound, self.token_provider_api.validate_v2_token, self.scoped_token_id, self.tenant['id']) def _check_scoped_tokens_are_valid(self): self.token_provider_api.validate_token(self.scoped_token_id) self.token_provider_api.validate_token( self.scoped_token_id, belongs_to=self.tenant['id']) self.token_provider_api.validate_v2_token(self.scoped_token_id) self.token_provider_api.validate_v2_token( self.scoped_token_id, belongs_to=self.tenant['id']) def _check_unscoped_tokens_are_valid(self): self.token_provider_api.validate_token(self.unscoped_token_id) self.token_provider_api.validate_v2_token(self.unscoped_token_id) def test_delete_unscoped_token(self): self.token_api.delete_token(self.unscoped_token_id) self._check_unscoped_tokens_are_invalid() self._check_scoped_tokens_are_valid() def test_delete_scoped_token_by_id(self): self.token_api.delete_token(self.scoped_token_id) self._check_scoped_tokens_are_invalid() self._check_unscoped_tokens_are_valid() def test_delete_scoped_token_by_user(self): self.token_api.delete_tokens(self.user['id']) # Since we are deleting all tokens for this user, they should all # now be invalid. self._check_scoped_tokens_are_invalid() self._check_unscoped_tokens_are_invalid() def test_delete_scoped_token_by_user_and_tenant(self): self.token_api.delete_tokens(self.user['id'], tenant_id=self.tenant['id']) self._check_scoped_tokens_are_invalid() self._check_unscoped_tokens_are_valid() class TrustTests(object): def create_sample_trust(self, new_id, remaining_uses=None): self.trustor = self.user_foo self.trustee = self.user_two trust_data = (self.trust_api.create_trust (new_id, {'trustor_user_id': self.trustor['id'], 'trustee_user_id': self.user_two['id'], 'project_id': self.tenant_bar['id'], 'expires_at': timeutils. parse_isotime('2031-02-18T18:10:00Z'), 'impersonation': True, 'remaining_uses': remaining_uses}, roles=[{"id": "member"}, {"id": "other"}, {"id": "browser"}])) return trust_data def test_delete_trust(self): new_id = uuid.uuid4().hex trust_data = self.create_sample_trust(new_id) trust_id = trust_data['id'] self.assertIsNotNone(trust_data) trust_data = self.trust_api.get_trust(trust_id) self.assertEqual(new_id, trust_data['id']) self.trust_api.delete_trust(trust_id) self.assertIsNone(self.trust_api.get_trust(trust_id)) def test_delete_trust_not_found(self): trust_id = uuid.uuid4().hex self.assertRaises(exception.TrustNotFound, self.trust_api.delete_trust, trust_id) def test_get_trust(self): new_id = uuid.uuid4().hex trust_data = self.create_sample_trust(new_id) trust_id = trust_data['id'] self.assertIsNotNone(trust_data) trust_data = self.trust_api.get_trust(trust_id) self.assertEqual(new_id, trust_data['id']) def test_create_trust(self): new_id = uuid.uuid4().hex trust_data = self.create_sample_trust(new_id) self.assertEqual(new_id, trust_data['id']) self.assertEqual(self.trustee['id'], trust_data['trustee_user_id']) self.assertEqual(self.trustor['id'], trust_data['trustor_user_id']) self.assertTrue(timeutils.normalize_time(trust_data['expires_at']) > timeutils.utcnow()) self.assertEqual([{'id': 'member'}, {'id': 'other'}, {'id': 'browser'}], trust_data['roles']) def test_list_trust_by_trustee(self): for i in range(3): self.create_sample_trust(uuid.uuid4().hex) trusts = self.trust_api.list_trusts_for_trustee(self.trustee['id']) self.assertEqual(len(trusts), 3) self.assertEqual(trusts[0]["trustee_user_id"], self.trustee['id']) trusts = self.trust_api.list_trusts_for_trustee(self.trustor['id']) self.assertEqual(len(trusts), 0) def test_list_trust_by_trustor(self): for i in range(3): self.create_sample_trust(uuid.uuid4().hex) trusts = self.trust_api.list_trusts_for_trustor(self.trustor['id']) self.assertEqual(len(trusts), 3) self.assertEqual(trusts[0]["trustor_user_id"], self.trustor['id']) trusts = self.trust_api.list_trusts_for_trustor(self.trustee['id']) self.assertEqual(len(trusts), 0) def test_list_trusts(self): for i in range(3): self.create_sample_trust(uuid.uuid4().hex) trusts = self.trust_api.list_trusts() self.assertEqual(len(trusts), 3) def test_trust_has_remaining_uses_positive(self): # create a trust with limited uses, check that we have uses left trust_data = self.create_sample_trust(uuid.uuid4().hex, remaining_uses=5) self.assertEqual(5, trust_data['remaining_uses']) # create a trust with unlimited uses, check that we have uses left trust_data = self.create_sample_trust(uuid.uuid4().hex) self.assertIsNone(trust_data['remaining_uses']) def test_trust_has_remaining_uses_negative(self): # try to create a trust with no remaining uses, check that it fails self.assertRaises(exception.ValidationError, self.create_sample_trust, uuid.uuid4().hex, remaining_uses=0) # try to create a trust with negative remaining uses, # check that it fails self.assertRaises(exception.ValidationError, self.create_sample_trust, uuid.uuid4().hex, remaining_uses=-12) def test_consume_use(self): # consume a trust repeatedly until it has no uses anymore trust_data = self.create_sample_trust(uuid.uuid4().hex, remaining_uses=2) self.trust_api.consume_use(trust_data['id']) t = self.trust_api.get_trust(trust_data['id']) self.assertEqual(1, t['remaining_uses']) self.trust_api.consume_use(trust_data['id']) # This was the last use, the trust isn't available anymore self.assertIsNone(self.trust_api.get_trust(trust_data['id'])) class CommonHelperTests(tests.TestCase): def test_format_helper_raises_malformed_on_missing_key(self): self.assertRaises(exception.MalformedEndpoint, core.format_url, "http://%(foo)s/%(bar)s", {"foo": "1"}) def test_format_helper_raises_malformed_on_wrong_type(self): self.assertRaises(exception.MalformedEndpoint, core.format_url, "http://%foo%s", {"foo": "1"}) def test_format_helper_raises_malformed_on_incomplete_format(self): self.assertRaises(exception.MalformedEndpoint, core.format_url, "http://%(foo)", {"foo": "1"}) class CatalogTests(object): def test_region_crud(self): # create region_id = uuid.uuid4().hex new_region = { 'id': region_id, 'description': uuid.uuid4().hex, } res = self.catalog_api.create_region( new_region.copy()) # Ensure that we don't need to have a # parent_region_id in the original supplied # ref dict, but that it will be returned from # the endpoint, with None value. expected_region = new_region.copy() expected_region['parent_region_id'] = None self.assertDictEqual(res, expected_region) # Test adding another region with the one above # as its parent. We will check below whether deleting # the parent successfully deletes any child regions. parent_region_id = region_id region_id = uuid.uuid4().hex new_region = { 'id': region_id, 'description': uuid.uuid4().hex, 'parent_region_id': parent_region_id } self.catalog_api.create_region( new_region.copy()) # list regions = self.catalog_api.list_regions() self.assertThat(regions, matchers.HasLength(2)) region_ids = [x['id'] for x in regions] self.assertIn(parent_region_id, region_ids) self.assertIn(region_id, region_ids) # delete self.catalog_api.delete_region(parent_region_id) self.assertRaises(exception.RegionNotFound, self.catalog_api.delete_region, parent_region_id) self.assertRaises(exception.RegionNotFound, self.catalog_api.get_region, parent_region_id) # Ensure the child is also gone... self.assertRaises(exception.RegionNotFound, self.catalog_api.get_region, region_id) def test_create_region_with_duplicate_id(self): region_id = uuid.uuid4().hex new_region = { 'id': region_id, 'description': uuid.uuid4().hex } self.catalog_api.create_region(new_region) # Create region again with duplicate id self.assertRaises(exception.Conflict, self.catalog_api.create_region, new_region) def test_get_region_404(self): self.assertRaises(exception.RegionNotFound, self.catalog_api.get_region, uuid.uuid4().hex) def test_delete_region_404(self): self.assertRaises(exception.RegionNotFound, self.catalog_api.delete_region, uuid.uuid4().hex) def test_create_region_invalid_parent_region_404(self): region_id = uuid.uuid4().hex new_region = { 'id': region_id, 'description': uuid.uuid4().hex, 'parent_region_id': 'nonexisting' } self.assertRaises(exception.RegionNotFound, self.catalog_api.create_region, new_region) def test_service_crud(self): # create service_id = uuid.uuid4().hex new_service = { 'id': service_id, 'type': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, } res = self.catalog_api.create_service( service_id, new_service.copy()) new_service['enabled'] = True self.assertDictEqual(new_service, res) # list services = self.catalog_api.list_services() self.assertIn(service_id, [x['id'] for x in services]) # delete self.catalog_api.delete_service(service_id) self.assertRaises(exception.ServiceNotFound, self.catalog_api.delete_service, service_id) self.assertRaises(exception.ServiceNotFound, self.catalog_api.get_service, service_id) def test_delete_service_with_endpoint(self): # create a service service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, } self.catalog_api.create_service(service['id'], service) # create an endpoint attached to the service endpoint = { 'id': uuid.uuid4().hex, 'region': uuid.uuid4().hex, 'interface': uuid.uuid4().hex[:8], 'url': uuid.uuid4().hex, 'service_id': service['id'], } self.catalog_api.create_endpoint(endpoint['id'], endpoint) # deleting the service should also delete the endpoint self.catalog_api.delete_service(service['id']) self.assertRaises(exception.EndpointNotFound, self.catalog_api.get_endpoint, endpoint['id']) self.assertRaises(exception.EndpointNotFound, self.catalog_api.delete_endpoint, endpoint['id']) def test_get_service_404(self): self.assertRaises(exception.ServiceNotFound, self.catalog_api.get_service, uuid.uuid4().hex) def test_delete_service_404(self): self.assertRaises(exception.ServiceNotFound, self.catalog_api.delete_service, uuid.uuid4().hex) def test_create_endpoint_404(self): endpoint = { 'id': uuid.uuid4().hex, 'service_id': uuid.uuid4().hex, } self.assertRaises(exception.ServiceNotFound, self.catalog_api.create_endpoint, endpoint['id'], endpoint) def test_get_endpoint_404(self): self.assertRaises(exception.EndpointNotFound, self.catalog_api.get_endpoint, uuid.uuid4().hex) def test_delete_endpoint_404(self): self.assertRaises(exception.EndpointNotFound, self.catalog_api.delete_endpoint, uuid.uuid4().hex) def test_create_endpoint(self): service = { 'id': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, } self.catalog_api.create_service(service['id'], service.copy()) endpoint = { 'id': uuid.uuid4().hex, 'region': "0" * 255, 'service_id': service['id'], 'interface': 'public', 'url': uuid.uuid4().hex, } self.catalog_api.create_endpoint(endpoint['id'], endpoint.copy()) def _create_endpoints(self): # Creates a service and 2 endpoints for the service in the same region. # The 'public' interface is enabled and the 'internal' interface is # disabled. def create_endpoint(service_id, region, **kwargs): id_ = uuid.uuid4().hex ref = { 'id': id_, 'interface': 'public', 'region': region, 'service_id': service_id, 'url': 'http://localhost/%s' % uuid.uuid4().hex, } ref.update(kwargs) self.catalog_api.create_endpoint(id_, ref) return ref # Create a service for use with the endpoints. service_id = uuid.uuid4().hex service_ref = { 'id': service_id, 'name': uuid.uuid4().hex, 'type': uuid.uuid4().hex, } self.catalog_api.create_service(service_id, service_ref) region = uuid.uuid4().hex # Create endpoints enabled_endpoint_ref = create_endpoint(service_id, region) disabled_endpoint_ref = create_endpoint( service_id, region, enabled=False, interface='internal') return service_ref, enabled_endpoint_ref, disabled_endpoint_ref def test_get_catalog_endpoint_disabled(self): """Get back only enabled endpoints when get the v2 catalog.""" service_ref, enabled_endpoint_ref, dummy_disabled_endpoint_ref = ( self._create_endpoints()) user_id = uuid.uuid4().hex project_id = uuid.uuid4().hex catalog = self.catalog_api.get_catalog(user_id, project_id) exp_entry = { 'id': enabled_endpoint_ref['id'], 'name': service_ref['name'], 'publicURL': enabled_endpoint_ref['url'], } region = enabled_endpoint_ref['region'] self.assertEqual(exp_entry, catalog[region][service_ref['type']]) def test_get_v3_catalog_endpoint_disabled(self): """Get back only enabled endpoints when get the v3 catalog.""" enabled_endpoint_ref = self._create_endpoints()[1] user_id = uuid.uuid4().hex project_id = uuid.uuid4().hex catalog = self.catalog_api.get_v3_catalog(user_id, project_id) endpoint_ids = [x['id'] for x in catalog[0]['endpoints']] self.assertEqual([enabled_endpoint_ref['id']], endpoint_ids) class PolicyTests(object): def _new_policy_ref(self): return { 'id': uuid.uuid4().hex, 'policy': uuid.uuid4().hex, 'type': uuid.uuid4().hex, 'endpoint_id': uuid.uuid4().hex, } def assertEqualPolicies(self, a, b): self.assertEqual(a['id'], b['id']) self.assertEqual(a['endpoint_id'], b['endpoint_id']) self.assertEqual(a['policy'], b['policy']) self.assertEqual(a['type'], b['type']) def test_create(self): ref = self._new_policy_ref() res = self.policy_api.create_policy(ref['id'], ref) self.assertEqualPolicies(ref, res) def test_get(self): ref = self._new_policy_ref() res = self.policy_api.create_policy(ref['id'], ref) res = self.policy_api.get_policy(ref['id']) self.assertEqualPolicies(ref, res) def test_list(self): ref = self._new_policy_ref() self.policy_api.create_policy(ref['id'], ref) res = self.policy_api.list_policies() res = [x for x in res if x['id'] == ref['id']][0] self.assertEqualPolicies(ref, res) def test_update(self): ref = self._new_policy_ref() self.policy_api.create_policy(ref['id'], ref) orig = ref ref = self._new_policy_ref() # (cannot change policy ID) self.assertRaises(exception.ValidationError, self.policy_api.update_policy, orig['id'], ref) ref['id'] = orig['id'] res = self.policy_api.update_policy(orig['id'], ref) self.assertEqualPolicies(ref, res) def test_delete(self): ref = self._new_policy_ref() self.policy_api.create_policy(ref['id'], ref) self.policy_api.delete_policy(ref['id']) self.assertRaises(exception.PolicyNotFound, self.policy_api.delete_policy, ref['id']) self.assertRaises(exception.PolicyNotFound, self.policy_api.get_policy, ref['id']) res = self.policy_api.list_policies() self.assertFalse(len([x for x in res if x['id'] == ref['id']])) def test_get_policy_404(self): self.assertRaises(exception.PolicyNotFound, self.policy_api.get_policy, uuid.uuid4().hex) def test_update_policy_404(self): ref = self._new_policy_ref() self.assertRaises(exception.PolicyNotFound, self.policy_api.update_policy, ref['id'], ref) def test_delete_policy_404(self): self.assertRaises(exception.PolicyNotFound, self.policy_api.delete_policy, uuid.uuid4().hex) class InheritanceTests(object): def test_inherited_role_grants_for_user(self): """Test inherited user roles. Test Plan: - Enable OS-INHERIT extension - Create 3 roles - Create a domain, with a project and a user - Check no roles yet exit - Assign a direct user role to the project and a (non-inherited) user role to the domain - Get a list of effective roles - should only get the one direct role - Now add an inherited user role to the domain - Get a list of effective roles - should have two roles, one direct and one by virtue of the inherited user role - Also get effective roles for the domain - the role marked as inherited should not show up """ self.config_fixture.config(group='os_inherit', enabled=True) role_list = [] for _ in range(3): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) # Create the first two roles - the domain one is not inherited self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role_list[0]['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role_list[1]['id']) # Now get the effective roles for the user and project, this # should only include the direct role assignment on the project combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(len(combined_list), 1) self.assertIn(role_list[0]['id'], combined_list) # Now add an inherited role on the domain self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain1['id'], role_id=role_list[2]['id'], inherited_to_projects=True) # Now get the effective roles for the user and project again, this # should now include the inherited role on the domain combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(len(combined_list), 2) self.assertIn(role_list[0]['id'], combined_list) self.assertIn(role_list[2]['id'], combined_list) # Finally, check that the inherited role does not appear as a valid # directly assigned role on the domain itself combined_role_list = self.assignment_api.get_roles_for_user_and_domain( user1['id'], domain1['id']) self.assertEqual(len(combined_role_list), 1) self.assertIn(role_list[1]['id'], combined_role_list) def test_inherited_role_grants_for_group(self): """Test inherited group roles. Test Plan: - Enable OS-INHERIT extension - Create 4 roles - Create a domain, with a project, user and two groups - Make the user a member of both groups - Check no roles yet exit - Assign a direct user role to the project and a (non-inherited) group role on the domain - Get a list of effective roles - should only get the one direct role - Now add two inherited group roles to the domain - Get a list of effective roles - should have three roles, one direct and two by virtue of inherited group roles """ self.config_fixture.config(group='os_inherit', enabled=True) role_list = [] for _ in range(4): role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_role(role['id'], role) role_list.append(role) domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'password': uuid.uuid4().hex, 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group1['id'], group1) group2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id'], 'enabled': True} self.identity_api.create_group(group2['id'], group2) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain1['id']} self.assignment_api.create_project(project1['id'], project1) self.identity_api.add_user_to_group(user1['id'], group1['id']) self.identity_api.add_user_to_group(user1['id'], group2['id']) roles_ref = self.assignment_api.list_grants( user_id=user1['id'], project_id=project1['id']) self.assertEqual(len(roles_ref), 0) # Create two roles - the domain one is not inherited self.assignment_api.create_grant(user_id=user1['id'], project_id=project1['id'], role_id=role_list[0]['id']) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain1['id'], role_id=role_list[1]['id']) # Now get the effective roles for the user and project, this # should only include the direct role assignment on the project combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(len(combined_list), 1) self.assertIn(role_list[0]['id'], combined_list) # Now add to more group roles, both inherited, to the domain self.assignment_api.create_grant(group_id=group2['id'], domain_id=domain1['id'], role_id=role_list[2]['id'], inherited_to_projects=True) self.assignment_api.create_grant(group_id=group2['id'], domain_id=domain1['id'], role_id=role_list[3]['id'], inherited_to_projects=True) # Now get the effective roles for the user and project again, this # should now include the inherited roles on the domain combined_list = self.assignment_api.get_roles_for_user_and_project( user1['id'], project1['id']) self.assertEqual(len(combined_list), 3) self.assertIn(role_list[0]['id'], combined_list) self.assertIn(role_list[2]['id'], combined_list) self.assertIn(role_list[3]['id'], combined_list) def test_list_projects_for_user_with_inherited_grants(self): """Test inherited group roles. Test Plan: - Enable OS-INHERIT extension - Create a domain, with two projects and a user - Assign an inherited user role on the domain, as well as a direct user role to a separate project in a different domain - Get a list of projects for user, should return all three projects """ self.config_fixture.config(group='os_inherit', enabled=True) domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain['id'], domain) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': domain['id'], 'enabled': True} self.identity_api.create_user(user1['id'], user1) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project1['id'], project1) project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project2['id'], project2) # Create 2 grants, one on a project and one inherited grant # on the domain self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_bar['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain['id'], role_id=self.role_admin['id'], inherited_to_projects=True) # Should get back all three projects, one by virtue of the direct # grant, plus both projects in the domain user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(len(user_projects), 3) def test_list_projects_for_user_with_inherited_group_grants(self): """Test inherited group roles. Test Plan: - Enable OS-INHERIT extension - Create two domains, each with two projects - Create a user and group - Make the user a member of the group - Assign a user role two projects, an inherited group role to one domain and an inherited regular role on the other domain - Get a list of projects for user, should return both pairs of projects from the domain, plus the one separate project """ self.config_fixture.config(group='os_inherit', enabled=True) domain = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain['id'], domain) domain2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain2['id'], domain2) project1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project1['id'], project1) project2 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.assignment_api.create_project(project2['id'], project2) project3 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain2['id']} self.assignment_api.create_project(project3['id'], project3) project4 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain2['id']} self.assignment_api.create_project(project4['id'], project4) user1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'password': uuid.uuid4().hex, 'domain_id': domain['id'], 'enabled': True} self.identity_api.create_user(user1['id'], user1) group1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': domain['id']} self.identity_api.create_group(group1['id'], group1) self.identity_api.add_user_to_group(user1['id'], group1['id']) # Create 4 grants: # - one user grant on a project in domain2 # - one user grant on a project in the default domain # - one inherited user grant on domain # - one inherited group grant on domain2 self.assignment_api.create_grant(user_id=user1['id'], project_id=project3['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=user1['id'], project_id=self.tenant_bar['id'], role_id=self.role_member['id']) self.assignment_api.create_grant(user_id=user1['id'], domain_id=domain['id'], role_id=self.role_admin['id'], inherited_to_projects=True) self.assignment_api.create_grant(group_id=group1['id'], domain_id=domain2['id'], role_id=self.role_admin['id'], inherited_to_projects=True) # Should get back all five projects, but without a duplicate for # project3 (since it has both a direct user role and an inherited role) user_projects = self.assignment_api.list_projects_for_user(user1['id']) self.assertEqual(len(user_projects), 5) class FilterTests(filtering.FilterTests): def test_list_users_filtered(self): domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(domain1['id'], domain1) for entity in ['user', 'group', 'project']: # Create 20 entities, 14 of which are in domain1 entity_list = self._create_test_data(entity, 6) domain1_entity_list = self._create_test_data(entity, 14, domain1['id']) # Should get back the 14 entities in domain1 hints = driver_hints.Hints() hints.add_filter('domain_id', domain1['id']) entities = self._list_entities(entity)(hints=hints) self.assertEqual(len(entities), 14) self._match_with_list(entities, domain1_entity_list) # Check the driver has removed the filter from the list hints self.assertFalse(hints.get_exact_filter_by_name('domain_id')) # Try filtering to get one an exact item out of the list hints = driver_hints.Hints() hints.add_filter('name', domain1_entity_list[10]['name']) entities = self._list_entities(entity)(hints=hints) self.assertEqual(len(entities), 1) self.assertEqual(entities[0]['id'], domain1_entity_list[10]['id']) # Check the driver has removed the filter from the list hints self.assertFalse(hints.get_exact_filter_by_name('name')) self._delete_test_data(entity, entity_list) self._delete_test_data(entity, domain1_entity_list) def test_list_users_inexact_filtered(self): # Create 20 users user_list = self._create_test_data('user', 20) # Set up some names that we can filter on user = user_list[5] user['name'] = 'The' self.identity_api.update_user(user['id'], user) user = user_list[6] user['name'] = 'The Ministry' self.identity_api.update_user(user['id'], user) user = user_list[7] user['name'] = 'The Ministry of' self.identity_api.update_user(user['id'], user) user = user_list[8] user['name'] = 'The Ministry of Silly' self.identity_api.update_user(user['id'], user) user = user_list[9] user['name'] = 'The Ministry of Silly Walks' self.identity_api.update_user(user['id'], user) # ...and one for useful case insensitivity testing user = user_list[10] user['name'] = 'The ministry of silly walks OF' self.identity_api.update_user(user['id'], user) hints = driver_hints.Hints() hints.add_filter('name', 'ministry', comparator='contains') users = self.identity_api.list_users(hints=hints) self.assertEqual(len(users), 5) self._match_with_list(users, user_list, list_start=6, list_end=11) #TODO(henry-nash) Check inexact filter has been removed. hints = driver_hints.Hints() hints.add_filter('name', 'The', comparator='startswith') users = self.identity_api.list_users(hints=hints) self.assertEqual(len(users), 6) self._match_with_list(users, user_list, list_start=5, list_end=11) #TODO(henry-nash) Check inexact filter has been removed. hints = driver_hints.Hints() hints.add_filter('name', 'of', comparator='endswith') users = self.identity_api.list_users(hints=hints) self.assertEqual(len(users), 2) self.assertEqual(users[0]['id'], user_list[7]['id']) self.assertEqual(users[1]['id'], user_list[10]['id']) #TODO(henry-nash) Check inexact filter has been removed. # TODO(henry-nash): Add some case sensitive tests. The issue # is that MySQL 0.7, by default, is installed in case # insensitive mode (which is what is run by default for our # SQL backend tests). For production deployments. OpenStack # assumes a case sensitive database. For these tests, therefore, we # need to be able to check the sensitivity of the database so as to # know whether to run case sensitive tests here. self._delete_test_data('user', user_list) def test_filter_sql_injection_attack(self): """Test against sql injection attack on filters Test Plan: - Attempt to get all entities back by passing a two-term attribute - Attempt to piggyback filter to damage DB (e.g. drop table) """ # Check we have some users users = self.identity_api.list_users() self.assertTrue(len(users) > 0) hints = driver_hints.Hints() hints.add_filter('name', "anything' or 'x'='x") users = self.identity_api.list_users(hints=hints) self.assertEqual(len(users), 0) # See if we can add a SQL command...use the group table instead of the # user table since 'user' is reserved word for SQLAlchemy. group = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'domain_id': DEFAULT_DOMAIN_ID} self.identity_api.create_group(group['id'], group) hints = driver_hints.Hints() hints.add_filter('name', "x'; drop table group") groups = self.identity_api.list_groups(hints=hints) self.assertEqual(len(groups), 0) groups = self.identity_api.list_groups() self.assertTrue(len(groups) > 0) class LimitTests(filtering.FilterTests): ENTITIES = ['user', 'group', 'project'] def setUp(self): """Setup for Limit Test Cases.""" self.domain1 = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex} self.assignment_api.create_domain(self.domain1['id'], self.domain1) self.addCleanup(self.clean_up_domain) self.entity_lists = {} self.domain1_entity_lists = {} for entity in self.ENTITIES: # Create 20 entities, 14 of which are in domain1 self.entity_lists[entity] = self._create_test_data(entity, 6) self.domain1_entity_lists[entity] = self._create_test_data( entity, 14, self.domain1['id']) self.addCleanup(self.clean_up_entities) def clean_up_domain(self): """Clean up domain test data from Limit Test Cases.""" self.domain1['enabled'] = False self.assignment_api.update_domain(self.domain1['id'], self.domain1) self.assignment_api.delete_domain(self.domain1['id']) del self.domain1 def clean_up_entities(self): """Clean up entity test data from Limit Test Cases.""" for entity in self.ENTITIES: self._delete_test_data(entity, self.entity_lists[entity]) self._delete_test_data(entity, self.domain1_entity_lists[entity]) del self.entity_lists del self.domain1_entity_lists def _test_list_entity_filtered_and_limited(self, entity): self.config_fixture.config(list_limit=10) # Should get back just 10 entities in domain1 hints = driver_hints.Hints() hints.add_filter('domain_id', self.domain1['id']) entities = self._list_entities(entity)(hints=hints) self.assertEqual(len(entities), hints.get_limit()['limit']) self.assertTrue(hints.get_limit()['truncated']) self._match_with_list(entities, self.domain1_entity_lists[entity]) # Override with driver specific limit if entity == 'project': self.config_fixture.config(group='assignment', list_limit=5) else: self.config_fixture.config(group='identity', list_limit=5) # Should get back just 5 users in domain1 hints = driver_hints.Hints() hints.add_filter('domain_id', self.domain1['id']) entities = self._list_entities(entity)(hints=hints) self.assertEqual(len(entities), hints.get_limit()['limit']) self._match_with_list(entities, self.domain1_entity_lists[entity]) # Finally, let's pretend we want to get the full list of entities, # even with the limits set, as part of some internal calculation. # Calling the API without a hints list should achieve this, and # return at least the 20 entries we created (there may be other # entities lying around created by other tests/setup). entities = self._list_entities(entity)() self.assertTrue(len(entities) >= 20) def test_list_users_filtered_and_limited(self): self._test_list_entity_filtered_and_limited('user') def test_list_groups_filtered_and_limited(self): self._test_list_entity_filtered_and_limited('group') def test_list_projects_filtered_and_limited(self): self._test_list_entity_filtered_and_limited('project') keystone-2014.1/keystone/tests/__init__.py0000664000175400017540000000175712323716272021733 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. # NOTE(dstanek): gettextutils.enable_lazy() must be called before # gettextutils._() is called to ensure it has the desired lazy lookup # behavior. This includes cases, like keystone.exceptions, where # gettextutils._() is called at import time. from keystone.openstack.common import gettextutils as _gettextutils _gettextutils.enable_lazy() from keystone.tests.core import * # flake8: noqa keystone-2014.1/keystone/tests/test_contrib_simple_cert.py0000664000175400017540000000460712323716272025256 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid from keystone.tests import test_v3 class BaseTestCase(test_v3.RestfulTestCase): EXTENSION_TO_ADD = 'simple_cert_extension' CA_PATH = '/v3/OS-SIMPLE-CERT/ca' CERT_PATH = '/v3/OS-SIMPLE-CERT/certificates' class TestSimpleCert(BaseTestCase): def request_cert(self, path): content_type = 'application/x-pem-file' response = self.request(app=self.public_app, method='GET', path=path, headers={'Accept': content_type}, expected_status=200) self.assertEqual(response.content_type.lower(), content_type) self.assertIn('---BEGIN', response.body) return response def test_ca_cert(self): self.request_cert(self.CA_PATH) def test_signing_cert(self): self.request_cert(self.CERT_PATH) def test_missing_file(self): # these files do not exist self.config_fixture.config(group='signing', ca_certs=uuid.uuid4().hex, certfile=uuid.uuid4().hex) for path in [self.CA_PATH, self.CERT_PATH]: self.request(app=self.public_app, method='GET', path=path, expected_status=500) class UUIDSimpleCertTests(BaseTestCase): def config_overrides(self): super(UUIDSimpleCertTests, self).config_overrides() self.config_fixture.config( group='token', provider='keystone.token.providers.uuid.Provider') def test_using_uuid_controller(self): for path in [self.CA_PATH, self.CERT_PATH]: self.request(app=self.public_app, method='GET', path=path, expected_status=403) keystone-2014.1/keystone/policy/0000775000175400017540000000000012323716511017741 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/policy/controllers.py0000664000175400017540000000361312323716267022674 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import controller from keystone.common import dependency @dependency.requires('policy_api') class PolicyV3(controller.V3Controller): collection_name = 'policies' member_name = 'policy' @controller.protected() def create_policy(self, context, policy): ref = self._assign_unique_id(self._normalize_dict(policy)) self._require_attribute(ref, 'blob') self._require_attribute(ref, 'type') ref = self.policy_api.create_policy(ref['id'], ref) return PolicyV3.wrap_member(context, ref) @controller.filterprotected('type') def list_policies(self, context, filters): hints = PolicyV3.build_driver_hints(context, filters) refs = self.policy_api.list_policies(hints=hints) return PolicyV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_policy(self, context, policy_id): ref = self.policy_api.get_policy(policy_id) return PolicyV3.wrap_member(context, ref) @controller.protected() def update_policy(self, context, policy_id, policy): ref = self.policy_api.update_policy(policy_id, policy) return PolicyV3.wrap_member(context, ref) @controller.protected() def delete_policy(self, context, policy_id): return self.policy_api.delete_policy(policy_id) keystone-2014.1/keystone/policy/core.py0000664000175400017540000000703112323716267021254 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Main entry point into the Policy service.""" import abc import six from keystone.common import dependency from keystone.common import manager from keystone import config from keystone import exception CONF = config.CONF @dependency.provider('policy_api') class Manager(manager.Manager): """Default pivot point for the Policy backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.policy.driver) def get_policy(self, policy_id): try: return self.driver.get_policy(policy_id) except exception.NotFound: raise exception.PolicyNotFound(policy_id=policy_id) def update_policy(self, policy_id, policy): if 'id' in policy and policy_id != policy['id']: raise exception.ValidationError('Cannot change policy ID') try: return self.driver.update_policy(policy_id, policy) except exception.NotFound: raise exception.PolicyNotFound(policy_id=policy_id) @manager.response_truncated def list_policies(self, hints=None): # NOTE(henry-nash): Since the advantage of filtering or list limiting # of policies at the driver level is minimal, we leave this to the # caller. return self.driver.list_policies() def delete_policy(self, policy_id): try: return self.driver.delete_policy(policy_id) except exception.NotFound: raise exception.PolicyNotFound(policy_id=policy_id) @six.add_metaclass(abc.ABCMeta) class Driver(object): def _get_list_limit(self): return CONF.policy.list_limit or CONF.list_limit @abc.abstractmethod def enforce(self, context, credentials, action, target): """Verify that a user is authorized to perform action. For more information on a full implementation of this see: `keystone.common.policy.enforce`. """ raise exception.NotImplemented() @abc.abstractmethod def create_policy(self, policy_id, policy): """Store a policy blob. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_policies(self): """List all policies.""" raise exception.NotImplemented() @abc.abstractmethod def get_policy(self, policy_id): """Retrieve a specific policy blob. :raises: keystone.exception.PolicyNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_policy(self, policy_id, policy): """Update a policy blob. :raises: keystone.exception.PolicyNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_policy(self, policy_id): """Remove a policy blob. :raises: keystone.exception.PolicyNotFound """ raise exception.NotImplemented() keystone-2014.1/keystone/policy/routers.py0000664000175400017540000000147012323716267022030 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import router from keystone.policy import controllers def append_v3_routers(mapper, routers): policy_controller = controllers.PolicyV3() routers.append(router.Router(policy_controller, 'policies', 'policy')) keystone-2014.1/keystone/policy/backends/0000775000175400017540000000000012323716511021513 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/policy/backends/sql.py0000664000175400017540000000553612323716272022701 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack LLC # # 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 keystone.common import sql from keystone.common.sql import migration_helpers from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.policy.backends import rules class PolicyModel(sql.ModelBase, sql.DictBase): __tablename__ = 'policy' attributes = ['id', 'blob', 'type'] id = sql.Column(sql.String(64), primary_key=True) blob = sql.Column(sql.JsonBlob(), nullable=False) type = sql.Column(sql.String(255), nullable=False) extra = sql.Column(sql.JsonBlob()) class Policy(rules.Policy): # Internal interface to manage the database def db_sync(self, version=None): migration.db_sync( sql.get_engine(), migration_helpers.find_migrate_repo(), version=version) @sql.handle_conflicts(conflict_type='policy') def create_policy(self, policy_id, policy): session = sql.get_session() with session.begin(): ref = PolicyModel.from_dict(policy) session.add(ref) return ref.to_dict() def list_policies(self): session = sql.get_session() refs = session.query(PolicyModel).all() return [ref.to_dict() for ref in refs] def _get_policy(self, session, policy_id): """Private method to get a policy model object (NOT a dictionary).""" ref = session.query(PolicyModel).get(policy_id) if not ref: raise exception.PolicyNotFound(policy_id=policy_id) return ref def get_policy(self, policy_id): session = sql.get_session() return self._get_policy(session, policy_id).to_dict() @sql.handle_conflicts(conflict_type='policy') def update_policy(self, policy_id, policy): session = sql.get_session() with session.begin(): ref = self._get_policy(session, policy_id) old_dict = ref.to_dict() old_dict.update(policy) new_policy = PolicyModel.from_dict(old_dict) ref.blob = new_policy.blob ref.type = new_policy.type ref.extra = new_policy.extra return ref.to_dict() def delete_policy(self, policy_id): session = sql.get_session() with session.begin(): ref = self._get_policy(session, policy_id) session.delete(ref) keystone-2014.1/keystone/policy/backends/rules.py0000664000175400017540000000675612323716267023245 0ustar jenkinsjenkins00000000000000# Copyright (c) 2011 OpenStack, LLC. # All Rights Reserved. # # 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. """Policy engine for keystone""" import os.path from keystone.common import utils from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import policy as common_policy from keystone import policy CONF = config.CONF LOG = log.getLogger(__name__) _ENFORCER = None _POLICY_PATH = None _POLICY_CACHE = {} def reset(): global _POLICY_PATH global _POLICY_CACHE global _ENFORCER _POLICY_PATH = None _POLICY_CACHE = {} _ENFORCER = None def init(): global _POLICY_PATH global _POLICY_CACHE global _ENFORCER if not _POLICY_PATH: _POLICY_PATH = CONF.policy_file if not os.path.exists(_POLICY_PATH): _POLICY_PATH = CONF.find_file(_POLICY_PATH) if not _ENFORCER: _ENFORCER = common_policy.Enforcer(policy_file=_POLICY_PATH) utils.read_cached_file(_POLICY_PATH, _POLICY_CACHE, reload_func=_set_rules) def _set_rules(data): global _ENFORCER default_rule = CONF.policy_default_rule _ENFORCER.set_rules(common_policy.Rules.load_json( data, default_rule)) def enforce(credentials, action, target, do_raise=True): """Verifies that the action is valid on the target in this context. :param credentials: user credentials :param action: string representing the action to be checked, which should be colon separated for clarity. :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. {'project_id': object.project_id} :raises: `exception.Forbidden` if verification fails. Actions should be colon separated for clarity. For example: * identity:list_users """ init() # Add the exception arguments if asked to do a raise extra = {} if do_raise: extra.update(exc=exception.ForbiddenAction, action=action, do_raise=do_raise) return _ENFORCER.enforce(action, target, credentials, **extra) class Policy(policy.Driver): def enforce(self, credentials, action, target): LOG.debug(_('enforce %(action)s: %(credentials)s'), { 'action': action, 'credentials': credentials}) enforce(credentials, action, target) def create_policy(self, policy_id, policy): raise exception.NotImplemented() def list_policies(self): raise exception.NotImplemented() def get_policy(self, policy_id): raise exception.NotImplemented() def update_policy(self, policy_id, policy): raise exception.NotImplemented() def delete_policy(self, policy_id): raise exception.NotImplemented() keystone-2014.1/keystone/policy/backends/__init__.py0000664000175400017540000000000012323716267023622 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/policy/__init__.py0000664000175400017540000000131112323716272022052 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.policy import controllers from keystone.policy.core import * from keystone.policy import routers keystone-2014.1/keystone/locale/0000775000175400017540000000000012323716511017701 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/he/0000775000175400017540000000000012323716511020275 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/he/LC_MESSAGES/0000775000175400017540000000000012323716511022062 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/he/LC_MESSAGES/keystone.po0000664000175400017540000013463612323716272024304 0ustar jenkinsjenkins00000000000000# Hebrew translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-01 20:03+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Hebrew " "(http://www.transifex.com/projects/p/openstack/language/he/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/pt/0000775000175400017540000000000012323716511020324 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pt/LC_MESSAGES/0000775000175400017540000000000012323716511022111 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pt/LC_MESSAGES/keystone.po0000664000175400017540000013464612323716272024334 0ustar jenkinsjenkins00000000000000# Portuguese translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Portuguese " "(http://www.transifex.com/projects/p/openstack/language/pt/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/id/0000775000175400017540000000000012323716511020275 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/id/LC_MESSAGES/0000775000175400017540000000000012323716511022062 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/id/LC_MESSAGES/keystone.po0000664000175400017540000013463712323716272024305 0ustar jenkinsjenkins00000000000000# Indonesian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Indonesian " "(http://www.transifex.com/projects/p/openstack/language/id/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/sv/0000775000175400017540000000000012323716511020331 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sv/LC_MESSAGES/0000775000175400017540000000000012323716511022116 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sv/LC_MESSAGES/keystone.po0000664000175400017540000013464012323716272024333 0ustar jenkinsjenkins00000000000000# Swedish translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Swedish " "(http://www.transifex.com/projects/p/openstack/language/sv/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/nl_NL/0000775000175400017540000000000012323716511020703 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/nl_NL/LC_MESSAGES/0000775000175400017540000000000012323716511022470 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/nl_NL/LC_MESSAGES/keystone.po0000664000175400017540000013467312323716272024713 0ustar jenkinsjenkins00000000000000# Dutch (Netherlands) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Dutch (Netherlands) " "(http://www.transifex.com/projects/p/openstack/language/nl_NL/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/eu_ES/0000775000175400017540000000000012323716511020701 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/eu_ES/LC_MESSAGES/0000775000175400017540000000000012323716511022466 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/eu_ES/LC_MESSAGES/keystone.po0000664000175400017540000013466112323716272024706 0ustar jenkinsjenkins00000000000000# Basque (Spain) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Basque (Spain) " "(http://www.transifex.com/projects/p/openstack/language/eu_ES/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/pl_PL/0000775000175400017540000000000012323716511020707 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pl_PL/LC_MESSAGES/0000775000175400017540000000000012323716511022474 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pl_PL/LC_MESSAGES/keystone.po0000664000175400017540000013475312323716272024716 0ustar jenkinsjenkins00000000000000# Polish (Poland) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-06-28 06:06+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: Polish (Poland) " "(http://www.transifex.com/projects/p/openstack/language/pl_PL/)\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && " "(n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/sl_SI/0000775000175400017540000000000012323716511020712 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sl_SI/LC_MESSAGES/0000775000175400017540000000000012323716511022477 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sl_SI/LC_MESSAGES/keystone.po0000664000175400017540000013475712323716272024725 0ustar jenkinsjenkins00000000000000# Slovenian (Slovenia) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-06-28 06:06+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: Slovenian (Slovenia) " "(http://www.transifex.com/projects/p/openstack/language/sl_SI/)\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 " "|| n%100==4 ? 2 : 3)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/en_US/0000775000175400017540000000000012323716511020712 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/en_US/LC_MESSAGES/0000775000175400017540000000000012323716511022477 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/en_US/LC_MESSAGES/keystone.po0000664000175400017540000013470312323716272024714 0ustar jenkinsjenkins00000000000000# English (United States) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: English (United States) " "(http://www.transifex.com/projects/p/openstack/language/en_US/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/es_MX/0000775000175400017540000000000012323716511020714 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/es_MX/LC_MESSAGES/0000775000175400017540000000000012323716511022501 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/es_MX/LC_MESSAGES/keystone.po0000664000175400017540000013466512323716272024725 0ustar jenkinsjenkins00000000000000# Spanish (Mexico) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-08-30 04:19+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Spanish (Mexico) " "(http://www.transifex.com/projects/p/openstack/language/es_MX/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/cs/0000775000175400017540000000000012323716511020306 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/cs/LC_MESSAGES/0000775000175400017540000000000012323716511022073 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/cs/LC_MESSAGES/keystone.po0000664000175400017540000013466712323716272024321 0ustar jenkinsjenkins00000000000000# Czech translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Czech " "(http://www.transifex.com/projects/p/openstack/language/cs/)\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ur/0000775000175400017540000000000012323716511020327 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ur/LC_MESSAGES/0000775000175400017540000000000012323716511022114 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ur/LC_MESSAGES/keystone.po0000664000175400017540000013463212323716272024332 0ustar jenkinsjenkins00000000000000# Urdu translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Urdu " "(http://www.transifex.com/projects/p/openstack/language/ur/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/da/0000775000175400017540000000000012323716511020265 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/da/LC_MESSAGES/0000775000175400017540000000000012323716511022052 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/da/LC_MESSAGES/keystone.po0000664000175400017540000013463612323716272024274 0ustar jenkinsjenkins00000000000000# Danish translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Danish " "(http://www.transifex.com/projects/p/openstack/language/da/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/hu/0000775000175400017540000000000012323716511020315 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/hu/LC_MESSAGES/0000775000175400017540000000000012323716511022102 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/hu/LC_MESSAGES/keystone.po0000664000175400017540000013672512323716272024325 0ustar jenkinsjenkins00000000000000# Hungarian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: # FIRST AUTHOR , 2012. # , 2012. msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2012-12-15 14:14+0000\n" "Last-Translator: kelemeng \n" "Language-Team: hu \n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s nem lehet üres" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "%(property_name)s nem lehet kevesebb, mint %(min_length)s karakter." #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "%(property_name)s nem lehet több, mint %(max_length)s karakter." #: keystone/clean.py:40 #, fuzzy, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "%(property_name)s nem %(display_expected_type)s" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "Többszörös azonosító: %s." #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "Többszörös név: %s." #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, fuzzy, python-format msgid "Unable to lookup user %s" msgstr "Nem vehetÅ‘ fel a token felhasználólistája." #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "Rosszul formázott végpont: %(url)s - ismeretlen kulcs: %(keyerror)s" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" "Rosszul formázott végpont: %(url)s - ismeretlen kulcs: %(keyerror)s " "(hiányoznak a zárójelek?)" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "Nem nyitható meg a sablonfájl: %s" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "arg_dict: %s" #: keystone/common/wsgi.py:210 #, fuzzy, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "Hitelesítés sikertelen. %s innen: %s" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "Az erÅ‘forrás nem található." #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "%(arg0)s indítása ezen: %(host)s:%(port)s" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, fuzzy, python-format msgid "LDAP init: url=%s" msgstr "FakeLdap elÅ‘készítési url=%s" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, fuzzy, python-format msgid "LDAP bind: dn=%s" msgstr "FakeLdap bind dn=%s" #: keystone/common/ldap/core.py:575 #, fuzzy, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "FakeLdap elem hozzáadása: dn=%s, attrs=%s" #: keystone/common/ldap/core.py:586 #, fuzzy, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "FakeLdap keresés itt: dn=%s hatókör=%s lekérdezés=%s" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, fuzzy, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "FakeLdap elem módosítása: dn=%s attrs=%s" #: keystone/common/ldap/core.py:672 #, fuzzy, python-format msgid "LDAP delete: dn=%s" msgstr "FakeLdap elem törlése: dn=%s" #: keystone/common/ldap/core.py:677 #, fuzzy, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "FakeLdap elem hozzáadása: dn=%s, attrs=%s" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "Nem sikerült %s kiiktatása" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "FakeLdap elem törlése: dn=%s" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 #, fuzzy msgid "Unable to sign token." msgstr "Nem vehetÅ‘ fel a token felhasználólistája." #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/zh_HK/0000775000175400017540000000000012323716511020704 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/zh_HK/LC_MESSAGES/0000775000175400017540000000000012323716511022471 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/zh_HK/LC_MESSAGES/keystone.po0000664000175400017540000013471312323716272024707 0ustar jenkinsjenkins00000000000000# Chinese (Traditional, Hong Kong SAR China) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Chinese (Hong Kong) " "(http://www.transifex.com/projects/p/openstack/language/zh_HK/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ms/0000775000175400017540000000000012323716511020320 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ms/LC_MESSAGES/0000775000175400017540000000000012323716511022105 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ms/LC_MESSAGES/keystone.po0000664000175400017540000013462512323716272024325 0ustar jenkinsjenkins00000000000000# Malay translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Malay " "(http://www.transifex.com/projects/p/openstack/language/ms/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/tl/0000775000175400017540000000000012323716511020320 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/tl/LC_MESSAGES/0000775000175400017540000000000012323716511022105 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/tl/LC_MESSAGES/keystone.po0000664000175400017540000013465612323716272024331 0ustar jenkinsjenkins00000000000000# Filipino (Philippines) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Tagalog " "(http://www.transifex.com/projects/p/openstack/language/tl/)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/tr_TR/0000775000175400017540000000000012323716511020733 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/tr_TR/LC_MESSAGES/0000775000175400017540000000000012323716511022520 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/tr_TR/LC_MESSAGES/keystone.po0000664000175400017540000013465612323716272024744 0ustar jenkinsjenkins00000000000000# Turkish (Turkey) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Turkish (Turkey) " "(http://www.transifex.com/projects/p/openstack/language/tr_TR/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/sw_KE/0000775000175400017540000000000012323716511020711 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sw_KE/LC_MESSAGES/0000775000175400017540000000000012323716511022476 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sw_KE/LC_MESSAGES/keystone.po0000664000175400017540000013466312323716272024720 0ustar jenkinsjenkins00000000000000# Swahili (Kenya) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Swahili (Kenya) " "(http://www.transifex.com/projects/p/openstack/language/sw_KE/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/es/0000775000175400017540000000000012323716511020310 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/es/LC_MESSAGES/0000775000175400017540000000000012323716511022075 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/es/LC_MESSAGES/keystone.po0000664000175400017540000014071612323716272024313 0ustar jenkinsjenkins00000000000000# Spanish translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-21 09:13+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: Spanish " "(http://www.transifex.com/projects/p/openstack/language/es/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s no puede estar vacío." #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "%(property_name)s no puede tener menos de %(min_length)s caracteres." #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "%(property_name)s no debe tener más de %(max_length)s caracteres." #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "No se puede eliminar un rol que no se ha otorgado, %s" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "ID duplicado, %s." #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "Nombre duplicado, %s." #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "No se ha encontrado el rol %s" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "El proyecto está inhabilitado: %s" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "El dominio está inhabilitado: %s" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "El ámbito para dominio y proyecto no está permitido" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "El ámbito para dominio y confianza no está permitido" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "El ámbito para proyecto y confianza no está permitido" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "Usuario no encontrado" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "No se ha podido buscar el usuario %s" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "El usuario está inhabilitado: %s" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" "Punto final formado incorrectamente %(url)s - clave desconocida " "%(keyerror)s" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" "Punto final con formato incorrecto %(url)s - clave desconocida " "%(keyerror)s (¿Faltan corchetes?)" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "No se puede abrir el archivo de plantilla %s" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "RBAC: continuando sin proyecto" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "RBAC: Continuando sin arrendatario" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "RBAC: Señal no válida" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "RBAC: Eludiendo autorización" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "RBAC: Autorización otorgada" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "RBAC: añadiendo parámetros de filtro de consultas (%s)" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "arg_dict: %s" #: keystone/common/wsgi.py:210 #, fuzzy, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "Ha fallado la autorización. %s de %s" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "El recurso no se ha podido encontrar." #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "Iniciando %(arg0)s en %(host)s:%(port)s" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "Error de servidor" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, fuzzy, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "Ãmbito de LDAP no válido: %s. Elija uno de los siguientes: " #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "Creación de LDAP %s" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "Actualización de LDAP %s" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "Supresión de LDAP %s" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "Inicialización de LDAP: url=%s" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "Enlace de LDAP: dn=%s" #: keystone/common/ldap/core.py:575 #, fuzzy, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "Adición de LDAP: dn=%s, attrs=%s" #: keystone/common/ldap/core.py:586 #, fuzzy, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "Búsqueda LDAP: dn=%s, scope=%s, query=%s, attrs=%s" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" "El servidor LDAP no soporta la paginación. Inhabilite la paginación en " "keystone.conf para evitar este mensaje." #: keystone/common/ldap/core.py:666 #, fuzzy, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "Modificación de LDAP: dn=%s, modlist=%s" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "Supresión de LDAP: dn=%s" #: keystone/common/ldap/core.py:677 #, fuzzy, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "LDAP delete_ext: dn=%s, serverctrls=%s" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "Usuario no encontrado en grupo" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, fuzzy, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "El usuario %s ya es miembro del grupo %s" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "No hay manejador para coincidencias de clase %s" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "la versión debe ser un entero" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "No se ha podido extraer %s" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "Supresión de elemento de FakeLDAP: dn=%s" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "La señal no pertenece al arrendatario especificado." #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "El dominio no predeterminado no está soportado" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "La señal con ámbito de dominio no está soportada" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "No se ha podido firmar la señal." #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/eu/0000775000175400017540000000000012323716511020312 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/eu/LC_MESSAGES/0000775000175400017540000000000012323716511022077 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/eu/LC_MESSAGES/keystone.po0000664000175400017540000013463612323716272024321 0ustar jenkinsjenkins00000000000000# Basque translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Basque " "(http://www.transifex.com/projects/p/openstack/language/eu/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ml_IN/0000775000175400017540000000000012323716511020677 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ml_IN/LC_MESSAGES/0000775000175400017540000000000012323716511022464 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ml_IN/LC_MESSAGES/keystone.po0000664000175400017540000013466712323716272024712 0ustar jenkinsjenkins00000000000000# Malayalam (India) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Malayalam (India) " "(http://www.transifex.com/projects/p/openstack/language/ml_IN/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ka_GE/0000775000175400017540000000000012323716511020647 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ka_GE/LC_MESSAGES/0000775000175400017540000000000012323716511022434 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ka_GE/LC_MESSAGES/keystone.po0000664000175400017540000013534512323716272024654 0ustar jenkinsjenkins00000000000000# Georgian (Georgia) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: # Nika Chkhikvishvili , 2013 msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: ka_GE \n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s áƒáƒ  შეიძლებრიყáƒáƒ¡ ცáƒáƒ áƒ˜áƒ”ლი." #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "რáƒáƒšáƒ˜ %s ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "დáƒáƒ›áƒ”ნი გáƒáƒ—იშულიáƒ: %s" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელი ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "LDAP %s შექმნáƒ" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "LDAP %s გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "LDAP %s წáƒáƒ¨áƒšáƒ" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/zh_CN/0000775000175400017540000000000012323716511020702 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/zh_CN/LC_MESSAGES/0000775000175400017540000000000012323716511022467 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/zh_CN/LC_MESSAGES/keystone.po0000664000175400017540000014016612323716272024704 0ustar jenkinsjenkins00000000000000# Chinese (China) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-21 06:08+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: Chinese (China) " "(http://www.transifex.com/projects/p/openstack/language/zh_CN/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s ä¸èƒ½ä¸ºç©ºã€‚" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "%(property_name)s ä¸èƒ½å°‘于 %(min_length)s 个字符。" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "%(property_name)s ä¸åº”该超过 %(max_length)s 个字符。" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "无法除去尚未授予的角色 %s" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "标识 %s é‡å¤ã€‚" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "åç§° %s é‡å¤ã€‚" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "找ä¸åˆ°è§’色 %s" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "项目已ç¦ç”¨ï¼š%s" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "域已ç¦ç”¨ï¼š%s" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "ä¸å…è®¸åŒæ—¶å°†ä½œç”¨åŸŸé™å®šåˆ°åŸŸå’Œé¡¹ç›®" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "ä¸å…è®¸åŒæ—¶å°†ä½œç”¨åŸŸé™å®šåˆ°åŸŸå’Œä¿¡ä»»" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "ä¸å…è®¸åŒæ—¶å°†ä½œç”¨åŸŸé™å®šåˆ°é¡¹ç›®å’Œä¿¡ä»»" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "找ä¸åˆ°ç”¨æˆ·" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "无法查找用户 %s" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "用户已ç¦ç”¨ï¼š%s" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "端点 %(url)s 的格å¼ä¸æ­£ç¡® - é”® %(keyerror)s 未知" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "端点 %(url)s 的格å¼ä¸æ­£ç¡® - é”® %(keyerror)s æœªçŸ¥ï¼ˆæ‚¨é—æ¼äº†æ–¹æ‹¬å·å—?)" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "æ— æ³•æ‰“å¼€æ¨¡æ¿æ–‡ä»¶ %s" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "RBAC:正在没有项目的情况下继续" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "RBAC:正在没有租户的情况下继续" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "RBAC:令牌无效" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "RBAC:正在绕过授æƒ" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "RBAC:已授予æƒé™" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "RBACï¼šæ­£åœ¨æ·»åŠ æŸ¥è¯¢è¿‡æ»¤å™¨å‚æ•° (%s)" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "arg_dict:%s" #: keystone/common/wsgi.py:210 #, fuzzy, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "授æƒå¤±è´¥ã€‚%s æ¥è‡ª %s" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "找ä¸åˆ°è¯¥èµ„æºã€‚" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "正在 %(host)s:%(port)s 上å¯åЍ %(arg0)s" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "æœåŠ¡å™¨é”™è¯¯" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, fuzzy, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "LDAP 作用域 %s 无效。请选择下列其中一项:" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "LDAP %s 创建" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "LDAP %s æ›´æ–°" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "LDAP %s 删除" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "LDAP åˆå§‹åŒ–:url=%s" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "LDAP 绑定:dn=%s" #: keystone/common/ldap/core.py:575 #, fuzzy, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "LDAP 添加:dn=%s,attrs=%s" #: keystone/common/ldap/core.py:586 #, fuzzy, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "LDAP æœç´¢ï¼šdn=%s,scope=%s,query=%s,attrs=%s" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "LDAP æœåС噍䏿”¯æŒé¡µé¢è°ƒåº¦ã€‚请在 keystone.conf 中ç¦ç”¨é¡µé¢è°ƒåº¦ä»¥é¿å…出现此消æ¯ã€‚" #: keystone/common/ldap/core.py:666 #, fuzzy, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "LDAP 修改:dn=%s,modlist=%s" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "LDAP 删除:dn=%s" #: keystone/common/ldap/core.py:677 #, fuzzy, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "LDAP delete_ext:dn=%s,serverctrls=%s" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "在组中找ä¸åˆ°ç”¨æˆ·" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, fuzzy, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "用户 %s 已是组 %s çš„æˆå‘˜" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "对于类型为 %s 的匹é…项,ä¸å­˜åœ¨ä»»ä½•处ç†ç¨‹åº" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "版本应该为整数" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "未能检出 %s" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "FakeLdap delete item:dn=%s" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "令牌ä¸å±žäºŽæŒ‡å®šçš„租户。" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "éžç¼ºçœåŸŸä¸å—支æŒ" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "作用域é™å®šåˆ°åŸŸçš„令牌ä¸å—支æŒ" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "无法对令牌进行签å。" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ar/0000775000175400017540000000000012323716511020303 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ar/LC_MESSAGES/0000775000175400017540000000000012323716511022070 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ar/LC_MESSAGES/keystone.po0000664000175400017540000013476412323716272024314 0ustar jenkinsjenkins00000000000000# Arabic translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-09-29 03:14+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Arabic " "(http://www.transifex.com/projects/p/openstack/language/ar/)\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : " "n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ja/0000775000175400017540000000000012323716511020273 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ja/LC_MESSAGES/0000775000175400017540000000000012323716511022060 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ja/LC_MESSAGES/keystone.po0000664000175400017540000013506112323716272024273 0ustar jenkinsjenkins00000000000000# Copyright (C) 2012 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: # Tomoyuki KATO , 2012. msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2012-11-03 01:25+0000\n" "Last-Translator: Tomoyuki KATO \n" "Language-Team: Japanese " "(http://www.transifex.com/projects/p/openstack/language/ja/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, fuzzy, python-format msgid "Unable to lookup user %s" msgstr "ユーザーリストã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã§ãã¾ã›ã‚“。" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 #, fuzzy msgid "Unable to sign token." msgstr "ユーザーリストã«ãƒˆãƒ¼ã‚¯ãƒ³ã‚’追加ã§ãã¾ã›ã‚“。" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/tl_PH/0000775000175400017540000000000012323716511020707 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/tl_PH/LC_MESSAGES/0000775000175400017540000000000012323716511022474 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/tl_PH/LC_MESSAGES/keystone.po0000664000175400017540000013467712323716272024723 0ustar jenkinsjenkins00000000000000# Filipino (Philippines) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-09-29 03:14+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Tagalog (Philippines) " "(http://www.transifex.com/projects/p/openstack/language/tl_PH/)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/sr/0000775000175400017540000000000012323716511020325 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sr/LC_MESSAGES/0000775000175400017540000000000012323716511022112 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sr/LC_MESSAGES/keystone.po0000664000175400017540000013504412323716272024326 0ustar jenkinsjenkins00000000000000# Serbian translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-23 18:30+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Serbian " "(http://www.transifex.com/projects/p/openstack/language/sr/)\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "GreÅ¡ka servera" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "syslog okruženje mora biti jedno od: %s" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/hr/0000775000175400017540000000000012323716511020312 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/hr/LC_MESSAGES/0000775000175400017540000000000012323716511022077 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/hr/LC_MESSAGES/keystone.po0000664000175400017540000013475512323716272024323 0ustar jenkinsjenkins00000000000000# Croatian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Croatian " "(http://www.transifex.com/projects/p/openstack/language/hr/)\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ko/0000775000175400017540000000000012323716511020312 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ko/LC_MESSAGES/0000775000175400017540000000000012323716511022077 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ko/LC_MESSAGES/keystone.po0000664000175400017540000013462712323716272024321 0ustar jenkinsjenkins00000000000000# Korean translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Korean " "(http://www.transifex.com/projects/p/openstack/language/ko/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/sq/0000775000175400017540000000000012323716511020324 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sq/LC_MESSAGES/0000775000175400017540000000000012323716511022111 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sq/LC_MESSAGES/keystone.po0000664000175400017540000013464212323716272024330 0ustar jenkinsjenkins00000000000000# Albanian translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-21 14:44+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Albanian " "(http://www.transifex.com/projects/p/openstack/language/sq/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/it/0000775000175400017540000000000012323716511020315 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/it/LC_MESSAGES/0000775000175400017540000000000012323716511022102 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/it/LC_MESSAGES/keystone.po0000664000175400017540000014055412323716272024320 0ustar jenkinsjenkins00000000000000# Italian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Italian " "(http://www.transifex.com/projects/p/openstack/language/it/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s non può essere vuoto." #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "%(property_name)s non può essere inferiore a %(min_length)s caratteri." #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "%(property_name)s non può essere superiore a %(max_length)s caratteri." #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "Impossibile rimuovere un ruolo che non è stato concesso, %s" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "ID duplicato, %s." #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "Nome duplicato, %s." #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "Ruolo %s non trovato" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "Il progetto è disabilitato: %s" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "Il dominio è disabilitato: %s" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "Il controllo sia del dominio che del progetto non è consentito" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "Il controllo sia del dominio che di trust non è consentito" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "Il controllo sia delprogetto che di trust non è consentito" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "Utente non trovato" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "Impossibile eseguire la ricerca dell'utente %s" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "L'utente è disabilitato: %s" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "Endpoint %(url)s non valdio - chiave sconosciuta %(keyerror)s" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" "Endpoint %(url)s non corretto - chiave sconosciuta %(keyerror)s(mancano " "le parentesi?)" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "Impossibile aprire il file di template %s" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "RBAC: si procede senza progetto" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "RBAC: si procede senza tenant" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "RBAC: token non valido" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "RBAC: autorizzazione oltrepassata" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "RBAC: autorizzazione concessa" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "RBAC: aggiunta parametri del filtro della query (%s)" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "arg_dict: %s" #: keystone/common/wsgi.py:210 #, fuzzy, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "Autorizzazione non riuscita. %s da %s" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "Impossibile trovare la risorsa." #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "Avvio %(arg0)s in %(host)s:%(port)s" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "Errore del server" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, fuzzy, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "Ambito LDAP non valido: %s. Sceglierne uno di: " #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "LDAP %s crea" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "LDAP %s aggiorna" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "LDAP %s elimina" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "LDAP inizializza: url=%s" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "LDAP bind: dn=%s" #: keystone/common/ldap/core.py:575 #, fuzzy, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "LDAP aggiunge: dn=%s, attrs=%s" #: keystone/common/ldap/core.py:586 #, fuzzy, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "Ricerca LDAP: dn=%s, scope=%s, query=%s, attrs=%s" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" "Il server LDAP non supporta la paginazione. Disabilitare la paginazione " "in keystone.conf per evitare questo messaggio." #: keystone/common/ldap/core.py:666 #, fuzzy, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "LDAP modifica: dn=%s, modlist=%s" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "LDAP elimina: dn=%s" #: keystone/common/ldap/core.py:677 #, fuzzy, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "LDAP delete_ext: dn=%s, serverctrls=%s" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "Utente non trovato nel gruppo" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, fuzzy, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "L'utente %s è già membro del gruppo %s" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "Nessun gestore per le corrispondenze di tipo %s" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "la versione deve essere un numero intero" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "Impossibile eseguire il checkout %s" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "FakeLdap elimina elemento: dn=%s" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "Il token non appartiene al tenant specificato." #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "Il dominio non predefinito non è supportato" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "L'ambito del dominio token non è supportato" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "Impossibile firmare il token." #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/gl/0000775000175400017540000000000012323716511020303 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/gl/LC_MESSAGES/0000775000175400017540000000000012323716511022070 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/gl/LC_MESSAGES/keystone.po0000664000175400017540000013464212323716272024307 0ustar jenkinsjenkins00000000000000# Galician translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Galician " "(http://www.transifex.com/projects/p/openstack/language/gl/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/kn/0000775000175400017540000000000012323716511020311 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/kn/LC_MESSAGES/0000775000175400017540000000000012323716511022076 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/kn/LC_MESSAGES/keystone.po0000664000175400017540000013463112323716272024313 0ustar jenkinsjenkins00000000000000# Kannada translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-09-29 03:14+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Kannada " "(http://www.transifex.com/projects/p/openstack/language/kn/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ca/0000775000175400017540000000000012323716511020264 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ca/LC_MESSAGES/0000775000175400017540000000000012323716511022051 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ca/LC_MESSAGES/keystone.po0000664000175400017540000013501112323716272024257 0ustar jenkinsjenkins00000000000000# Catalan translations for OpenStack Keystone. # Copyright (C) 2012 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: # Sergi Almacellas , 2012. msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2012-11-03 03:08+0000\n" "Last-Translator: Sergi Almacellas \n" "Language-Team: ca \n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, fuzzy, python-format msgid "Unable to lookup user %s" msgstr "No es pot afegir el token a la llista d'usuaris." #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 #, fuzzy msgid "Unable to sign token." msgstr "No es pot afegir el token a la llista d'usuaris." #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/fil/0000775000175400017540000000000012323716511020453 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fil/LC_MESSAGES/0000775000175400017540000000000012323716511022240 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fil/LC_MESSAGES/keystone.po0000664000175400017540000013464212323716272024457 0ustar jenkinsjenkins00000000000000# Filipino translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-09-29 03:14+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Filipino " "(http://www.transifex.com/projects/p/openstack/language/fil/)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/zh_TW/0000775000175400017540000000000012323716511020734 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/zh_TW/LC_MESSAGES/0000775000175400017540000000000012323716511022521 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/zh_TW/LC_MESSAGES/keystone.po0000664000175400017540000014023712323716272024735 0ustar jenkinsjenkins00000000000000# Chinese (Taiwan) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-22 03:11+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: Chinese (Taiwan) " "(http://www.transifex.com/projects/p/openstack/language/zh_TW/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s ä¸èƒ½æ˜¯ç©ºçš„。" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "%(property_name)s ä¸èƒ½å°‘æ–¼ %(min_length)s 個字元。" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "%(property_name)s 䏿‡‰è¶…éŽ %(max_length)s 個字元。" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "無法移除尚未授權的角色,%s" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "é‡è¤‡çš„ ID,%s。" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "é‡è¤‡çš„å稱,%s。" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "找ä¸åˆ°è§’色 %s" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "å·²åœç”¨å°ˆæ¡ˆï¼š%s" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "å·²åœç”¨ç¶²åŸŸï¼š%s" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "ä¸å®¹è¨±å°‡ç¯„åœåŒæ™‚設定為網域åŠå°ˆæ¡ˆ" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "ä¸å®¹è¨±å°‡ç¯„åœåŒæ™‚設定為網域åŠä¿¡ä»»" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "ä¸å®¹è¨±å°‡ç¯„åœåŒæ™‚設定為專案åŠä¿¡ä»»" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "找ä¸åˆ°ä½¿ç”¨è€…" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "無法查閱使用者 %s" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "å·²åœç”¨ä½¿ç”¨è€…:%s" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "端點 %(url)s 的格å¼ä¸æ­£ç¢º - 䏿˜Žçš„ç´¢å¼•éµ %(keyerror)s" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "端點 %(url)s 的格å¼ä¸æ­£ç¢º - 䏿˜Žçš„ç´¢å¼•éµ %(keyerror)sï¼ˆéºæ¼äº†æ–¹æ‹¬å¼§å—Žï¼Ÿï¼‰" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "無法開啟範本檔 %s" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "RBAC:在沒有專案的情æ³ä¸‹ç¹¼çºŒä½œæ¥­" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "RBAC:在沒有 Tenant 的情æ³ä¸‹ç¹¼çºŒä½œæ¥­" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "RBAC:無效的記號" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "RBACï¼šæ­£åœ¨ç•¥éŽæŽˆæ¬Š" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "RBAC:已授與權é™" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "RBACï¼šæ­£åœ¨æ–°å¢žæŸ¥è©¢éŽæ¿¾å™¨åƒæ•¸ (%s)" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "arg_dict:%s" #: keystone/common/wsgi.py:210 #, fuzzy, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "授權失敗。%s(自 %s)" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "找ä¸åˆ°è³‡æºã€‚" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "正在 %(host)s:%(port)s 上啟動 %(arg0)s" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "伺æœå™¨éŒ¯èª¤" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, fuzzy, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "無效的 LDAP 範åœï¼š%sã€‚è«‹é¸æ“‡ä¸‹åˆ—其中一個:" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "LDAP %s 建立" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "LDAP %s æ›´æ–°" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "LDAP %s 刪除" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "LDAP 起始設定:URL = %s" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "LDAP 連çµï¼šDN = %s" #: keystone/common/ldap/core.py:575 #, fuzzy, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "LDAP 新增:DN = %s,屬性 = %s" #: keystone/common/ldap/core.py:586 #, fuzzy, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "LDAP æœå°‹ï¼šDN = %sï¼Œç¯„åœ = %s,查詢 = %s,屬性 = %s" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "「LDAP 伺æœå™¨ã€ä¸æ”¯æ´åˆ†é ã€‚請在 keystone.conf 中åœç”¨åˆ†é ä»¥é¿å…此訊æ¯ã€‚" #: keystone/common/ldap/core.py:666 #, fuzzy, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "LDAP 修改:DN = %s,Modlist = %s" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "LDAP 刪除:DN = %s" #: keystone/common/ldap/core.py:677 #, fuzzy, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "LDAP delete_ext:DN = %s,Serverctrls = %s" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "在群組中找ä¸åˆ°ä½¿ç”¨è€…" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, fuzzy, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "使用者 %s 已是群組 %s çš„æˆå“¡" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "類型為 %s 的相符項沒有處ç†ç¨‹å¼" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "版本應該是整數" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "無法移出 %s" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "FakeLdap 刪除項目:DN = %s" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "記號ä¸å±¬æ–¼æ‰€æŒ‡å®šçš„ Tenant。" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "䏿”¯æ´éžé è¨­ç¶²åŸŸ" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "䏿”¯æ´ç¶²åŸŸç¯„åœçš„記號" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "無法簽署記號。" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/bn_IN/0000775000175400017540000000000012323716511020666 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/bn_IN/LC_MESSAGES/0000775000175400017540000000000012323716511022453 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/bn_IN/LC_MESSAGES/keystone.po0000664000175400017540000013466312323716272024675 0ustar jenkinsjenkins00000000000000# Bengali (India) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Bengali (India) " "(http://www.transifex.com/projects/p/openstack/language/bn_IN/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/el/0000775000175400017540000000000012323716511020301 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/el/LC_MESSAGES/0000775000175400017540000000000012323716511022066 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/el/LC_MESSAGES/keystone.po0000664000175400017540000013463412323716272024306 0ustar jenkinsjenkins00000000000000# Greek translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-21 14:44+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Greek " "(http://www.transifex.com/projects/p/openstack/language/el/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ro/0000775000175400017540000000000012323716511020321 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ro/LC_MESSAGES/0000775000175400017540000000000012323716511022106 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ro/LC_MESSAGES/keystone.po0000664000175400017540000013471112323716272024322 0ustar jenkinsjenkins00000000000000# Romanian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-06-08 07:51+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: Romanian " "(http://www.transifex.com/projects/p/openstack/language/ro/)\n" "Plural-Forms: nplurals=3; " "plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1))\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/is_IS/0000775000175400017540000000000012323716511020707 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/is_IS/LC_MESSAGES/0000775000175400017540000000000012323716511022474 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/is_IS/LC_MESSAGES/keystone.po0000664000175400017540000013467312323716272024717 0ustar jenkinsjenkins00000000000000# Icelandic (Iceland) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-12-19 05:30+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Icelandic (Iceland) " "(http://www.transifex.com/projects/p/openstack/language/is_IS/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/hi/0000775000175400017540000000000012323716511020301 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/hi/LC_MESSAGES/0000775000175400017540000000000012323716511022066 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/hi/LC_MESSAGES/keystone.po0000664000175400017540000013463412323716272024306 0ustar jenkinsjenkins00000000000000# Hindi translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-08-30 04:19+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Hindi " "(http://www.transifex.com/projects/p/openstack/language/hi/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/te_IN/0000775000175400017540000000000012323716511020677 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/te_IN/LC_MESSAGES/0000775000175400017540000000000012323716511022464 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/te_IN/LC_MESSAGES/keystone.po0000664000175400017540000013465012323716272024702 0ustar jenkinsjenkins00000000000000# Telugu (India) translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-24 05:56+0000\n" "Last-Translator: Tom Fifield \n" "Language-Team: Telugu (India) " "(http://www.transifex.com/projects/p/openstack/language/te_IN/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ru_RU/0000775000175400017540000000000012323716511020735 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ru_RU/LC_MESSAGES/0000775000175400017540000000000012323716511022522 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ru_RU/LC_MESSAGES/keystone.po0000664000175400017540000013500212323716272024730 0ustar jenkinsjenkins00000000000000# Russian (Russia) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Russian (Russia) " "(http://www.transifex.com/projects/p/openstack/language/ru_RU/)\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/en_AU/0000775000175400017540000000000012323716511020670 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/en_AU/LC_MESSAGES/0000775000175400017540000000000012323716511022455 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/en_AU/LC_MESSAGES/keystone.po0000664000175400017540000013467312323716272024700 0ustar jenkinsjenkins00000000000000# English (Australia) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: English (Australia) " "(http://www.transifex.com/projects/p/openstack/language/en_AU/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/mr_IN/0000775000175400017540000000000012323716511020705 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/mr_IN/LC_MESSAGES/0000775000175400017540000000000012323716511022472 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/mr_IN/LC_MESSAGES/keystone.po0000664000175400017540000013466312323716272024714 0ustar jenkinsjenkins00000000000000# Marathi (India) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Marathi (India) " "(http://www.transifex.com/projects/p/openstack/language/mr_IN/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/fr/0000775000175400017540000000000012323716511020310 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fr/LC_MESSAGES/0000775000175400017540000000000012323716511022075 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fr/LC_MESSAGES/keystone.po0000664000175400017540000013463512323716272024316 0ustar jenkinsjenkins00000000000000# French translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: French " "(http://www.transifex.com/projects/p/openstack/language/fr/)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/fi_FI/0000775000175400017540000000000012323716511020655 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fi_FI/LC_MESSAGES/0000775000175400017540000000000012323716511022442 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fi_FI/LC_MESSAGES/keystone.po0000664000175400017540000013466712323716272024670 0ustar jenkinsjenkins00000000000000# Finnish (Finland) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Finnish (Finland) " "(http://www.transifex.com/projects/p/openstack/language/fi_FI/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/nb/0000775000175400017540000000000012323716511020300 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/nb/LC_MESSAGES/0000775000175400017540000000000012323716511022065 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/nb/LC_MESSAGES/keystone.po0000664000175400017540000013466412323716272024310 0ustar jenkinsjenkins00000000000000# Norwegian Bokmål translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Norwegian Bokmål " "(http://www.transifex.com/projects/p/openstack/language/nb/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/it_IT/0000775000175400017540000000000012323716511020711 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/it_IT/LC_MESSAGES/0000775000175400017540000000000012323716511022476 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/it_IT/LC_MESSAGES/keystone.po0000664000175400017540000013466312323716272024720 0ustar jenkinsjenkins00000000000000# Italian (Italy) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Italian (Italy) " "(http://www.transifex.com/projects/p/openstack/language/it_IT/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/bs/0000775000175400017540000000000012323716511020305 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/bs/LC_MESSAGES/0000775000175400017540000000000012323716511022072 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/bs/LC_MESSAGES/keystone.po0000664000175400017540000013475512323716272024316 0ustar jenkinsjenkins00000000000000# Bosnian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Bosnian " "(http://www.transifex.com/projects/p/openstack/language/bs/)\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ru/0000775000175400017540000000000012323716511020327 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ru/LC_MESSAGES/0000775000175400017540000000000012323716511022114 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ru/LC_MESSAGES/keystone.po0000664000175400017540000013475512323716272024340 0ustar jenkinsjenkins00000000000000# Russian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Russian " "(http://www.transifex.com/projects/p/openstack/language/ru/)\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/km/0000775000175400017540000000000012323716511020310 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/km/LC_MESSAGES/0000775000175400017540000000000012323716511022075 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/km/LC_MESSAGES/keystone.po0000664000175400017540000013462512323716272024315 0ustar jenkinsjenkins00000000000000# Khmer translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Khmer " "(http://www.transifex.com/projects/p/openstack/language/km/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/en_GB/0000775000175400017540000000000012323716511020653 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/en_GB/LC_MESSAGES/0000775000175400017540000000000012323716511022440 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/en_GB/LC_MESSAGES/keystone.po0000664000175400017540000013470512323716272024657 0ustar jenkinsjenkins00000000000000# English (United Kingdom) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: English (United Kingdom) " "(http://www.transifex.com/projects/p/openstack/language/en_GB/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/bg_BG/0000775000175400017540000000000012323716511020641 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/bg_BG/LC_MESSAGES/0000775000175400017540000000000012323716511022426 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/bg_BG/LC_MESSAGES/keystone.po0000664000175400017540000013467512323716272024653 0ustar jenkinsjenkins00000000000000# Bulgarian (Bulgaria) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Bulgarian (Bulgaria) " "(http://www.transifex.com/projects/p/openstack/language/bg_BG/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ta/0000775000175400017540000000000012323716511020305 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ta/LC_MESSAGES/0000775000175400017540000000000012323716511022072 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ta/LC_MESSAGES/keystone.po0000664000175400017540000013462312323716272024310 0ustar jenkinsjenkins00000000000000# Tamil translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-24 06:02+0000\n" "Last-Translator: Tom Fifield \n" "Language-Team: Tamil " "(http://www.transifex.com/projects/p/openstack/language/ta/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ko_KR/0000775000175400017540000000000012323716511020706 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ko_KR/LC_MESSAGES/0000775000175400017540000000000012323716511022473 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ko_KR/LC_MESSAGES/keystone.po0000664000175400017540000013463312323716272024712 0ustar jenkinsjenkins00000000000000# Korean (South Korea) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: # Sung Jin Gang , 2013. msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-03-21 18:34+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: ko_KR \n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/keystone.pot0000664000175400017540000013460312323716272022301 0ustar jenkinsjenkins00000000000000# Translations template for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # FIRST AUTHOR , 2014. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: keystone " "jenkins.keystone.propose.translation.update.527\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/ne/0000775000175400017540000000000012323716511020303 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ne/LC_MESSAGES/0000775000175400017540000000000012323716511022070 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/ne/LC_MESSAGES/keystone.po0000664000175400017540000013463612323716272024312 0ustar jenkinsjenkins00000000000000# Nepali translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-09-04 23:27+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Nepali " "(http://www.transifex.com/projects/p/openstack/language/ne/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/pa_IN/0000775000175400017540000000000012323716511020667 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pa_IN/LC_MESSAGES/0000775000175400017540000000000012323716511022454 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pa_IN/LC_MESSAGES/keystone.po0000664000175400017540000013470712323716272024675 0ustar jenkinsjenkins00000000000000# Punjabi (Gurmukhi, India) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-12-19 05:30+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Panjabi (Punjabi) (India) " "(http://www.transifex.com/projects/p/openstack/language/pa_IN/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/he_IL/0000775000175400017540000000000012323716511020661 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/he_IL/LC_MESSAGES/0000775000175400017540000000000012323716511022446 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/he_IL/LC_MESSAGES/keystone.po0000664000175400017540000013466312323716272024670 0ustar jenkinsjenkins00000000000000# Hebrew (Israel) translations for keystone. # Copyright (C) 2014 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2014-03-01 20:03+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Hebrew (Israel) " "(http://www.transifex.com/projects/p/openstack/language/he_IL/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/fa/0000775000175400017540000000000012323716511020267 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fa/LC_MESSAGES/0000775000175400017540000000000012323716511022054 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/fa/LC_MESSAGES/keystone.po0000664000175400017540000013463112323716272024271 0ustar jenkinsjenkins00000000000000# Persian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-11-27 07:37+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Persian " "(http://www.transifex.com/projects/p/openstack/language/fa/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/uk/0000775000175400017540000000000012323716511020320 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/uk/LC_MESSAGES/0000775000175400017540000000000012323716511022105 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/uk/LC_MESSAGES/keystone.po0000664000175400017540000013476112323716272024326 0ustar jenkinsjenkins00000000000000# Ukrainian translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-07-29 22:01+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Ukrainian " "(http://www.transifex.com/projects/p/openstack/language/uk/)\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/pt_BR/0000775000175400017540000000000012323716511020707 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pt_BR/LC_MESSAGES/0000775000175400017540000000000012323716511022474 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/pt_BR/LC_MESSAGES/keystone.po0000664000175400017540000013465312323716272024715 0ustar jenkinsjenkins00000000000000# Portuguese (Brazil) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2012-11-02 18:30+0000\n" "Last-Translator: FULL NAME \n" "Language-Team: Portuguese (Brazil) " "(http://www.transifex.com/projects/p/openstack/language/pt_BR/)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/sk/0000775000175400017540000000000012323716511020316 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sk/LC_MESSAGES/0000775000175400017540000000000012323716511022103 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/sk/LC_MESSAGES/keystone.po0000664000175400017540000013467112323716272024324 0ustar jenkinsjenkins00000000000000# Slovak translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-08-30 04:19+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Slovak " "(http://www.transifex.com/projects/p/openstack/language/sk/)\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/de/0000775000175400017540000000000012323716511020271 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/de/LC_MESSAGES/0000775000175400017540000000000012323716511022056 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/de/LC_MESSAGES/keystone.po0000664000175400017540000014111512323716272024266 0ustar jenkinsjenkins00000000000000# German translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-22 03:45+0000\n" "Last-Translator: daisy.ycguo \n" "Language-Team: German " "(http://www.transifex.com/projects/p/openstack/language/de/)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "%s darf nicht leer sein." #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "%(property_name)s darf nicht kleiner als %(min_length)s Zeichen sein." #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "%(property_name)s sollte nicht größer als %(max_length)s Zeichen sein." #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "Nicht gewährte Rolle kann nicht entfernt werden, %s" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "Doppelte ID, %s." #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "Doppelter Name, %s." #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "Rolle %s nicht gefunden" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "Projekt ist inaktiviert: %s" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "Domäne ist inaktiviert: %s" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "Scoping sowohl auf 'domain' als auch auf 'project' ist nicht zulässig" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "Scoping sowohl auf 'domain' als auch auf 'trust' ist nicht zulässig" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "Scoping sowohl auf 'project' als auch auf 'trust' ist nicht zulässig" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "Benutzer nicht gefunden" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "Suche nach Benutzer %s nicht möglich" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "Benutzer ist inaktiviert: %s" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "Fehlerhafter Endpunkt %(url)s - unbekannter Schlüssel %(keyerror)s" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" "Fehlerhafter Endpunkt %(url)s - unbekannter Schlüssel %(keyerror)s " "(fehlende Klammer?)" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "Vorlagendatei %s kann nicht geöffnet werden" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "Rollenbasierte Zugriffssteuerung: Fortfahren ohne Projekt" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "Rollenbasierte Zugriffssteuerung: Fortsetzung ohne Nutzer" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "Rollenbasierte Zugriffssteuerung: Ungültiges Token" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "Rollenbasierte Zugriffssteuerung: Umgehen von Autorisierung" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "Rollenbasierte Zugriffssteuerung: Autorisierung erteilt" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" "Rollenbasierte Zugriffssteuerung: Hinzufügen von Abfragefilterparametern " "(%s)" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "arg_dict: %s" #: keystone/common/wsgi.py:210 #, fuzzy, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "Autorisierung fehlgeschlagen. %s von %s" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "Die Ressource konnte nicht gefunden werden." #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "Starten von %(arg0)s auf %(host)s:%(port)s" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "Serverfehler" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, fuzzy, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "Ungültiger LDAP-Umfang: %s. Wählen Sie aus: " #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "LDAP %s erstellen" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "LDAP %s aktualisieren" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "LDAP %s löschen" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "LDAP starten: url=%s" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "LDAP binden: dn=%s" #: keystone/common/ldap/core.py:575 #, fuzzy, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "LDAP hinzufügen: dn=%s, attrs=%s" #: keystone/common/ldap/core.py:586 #, fuzzy, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "LDAP-Suche: dn=%s, scope=%s, query=%s, attrs=%s" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" "LDAP-Server unterstützt Paging nicht. Inaktivieren Sie das Paging in " "keystone.conf, um diese Nachricht zu verhindern." #: keystone/common/ldap/core.py:666 #, fuzzy, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "LDAP ändern: dn=%s, modlist=%s" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "LDAP löschen: dn=%s" #: keystone/common/ldap/core.py:677 #, fuzzy, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "LDAP-'delete_ext': dn=%s, serverctrls=%s" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "Benutzer nicht in Gruppe gefunden" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, fuzzy, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "Benutzer %s ist bereits Mitglied der Gruppe %s." #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "Kein Handler für Übereinstimmungen des Typs %s" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "Version sollte eine Ganzzahl sein" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "%s wurde nicht ausgecheckt" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "FakeLdap-Element löschen: dn=%s" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "Token gehört nicht zu angegebenem Nutzer." #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "Nicht-Standard-Domäne wird nicht unterstützt" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "Bereichsorientiertes Token der Domäne wird nicht unterstützt" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "Token kann nicht unterzeichnet werden." #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/locale/vi_VN/0000775000175400017540000000000012323716511020722 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/vi_VN/LC_MESSAGES/0000775000175400017540000000000012323716511022507 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/locale/vi_VN/LC_MESSAGES/keystone.po0000664000175400017540000013466712323716272024735 0ustar jenkinsjenkins00000000000000# Vietnamese (Vietnam) translations for keystone. # Copyright (C) 2013 OpenStack Foundation # This file is distributed under the same license as the keystone project. # # Translators: msgid "" msgstr "" "Project-Id-Version: Keystone\n" "Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n" "POT-Creation-Date: 2014-03-26 06:00+0000\n" "PO-Revision-Date: 2013-05-17 16:06+0000\n" "Last-Translator: openstackjenkins \n" "Language-Team: Vietnamese (Viet Nam) " "(http://www.transifex.com/projects/p/openstack/language/vi_VN/)\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" #: keystone/clean.py:24 #, python-format msgid "%s cannot be empty." msgstr "" #: keystone/clean.py:26 #, python-format msgid "%(property_name)s cannot be less than %(min_length)s characters." msgstr "" #: keystone/clean.py:31 #, python-format msgid "%(property_name)s should not be greater than %(max_length)s characters." msgstr "" #: keystone/clean.py:40 #, python-format msgid "%(property_name)s is not a %(display_expected_type)s" msgstr "" #: keystone/exception.py:49 msgid "missing exception kwargs (programmer error)" msgstr "" #: keystone/exception.py:79 #, python-format msgid "" "Expecting to find %(attribute)s in %(target)s. The server could not " "comply with the request since it is either malformed or otherwise " "incorrect. The client is assumed to be in error." msgstr "" #: keystone/exception.py:88 msgid "" "Timestamp not in expected format. The server could not comply with the " "request since it is either malformed or otherwise incorrect. The client " "is assumed to be in error." msgstr "" #: keystone/exception.py:97 #, python-format msgid "" "String length exceeded.The length of string '%(string)s' exceeded the " "limit of column %(type)s(CHAR(%(length)d))." msgstr "" #: keystone/exception.py:103 #, python-format msgid "" "Request attribute %(attribute)s must be less than or equal to %(size)i. " "The server could not comply with the request because the attribute size " "is invalid (too large). The client is assumed to be in error." msgstr "" #: keystone/exception.py:113 msgid "" "The certificates you requested are not available. It is likely that this " "server does not use PKI tokens otherwise this is the result of " "misconfiguration." msgstr "" #: keystone/exception.py:132 msgid "The request you have made requires authentication." msgstr "" #: keystone/exception.py:138 msgid "Authentication plugin error." msgstr "" #: keystone/exception.py:146 #, python-format msgid "Unable to find valid groups while using mapping %(mapping_id)s" msgstr "" #: keystone/exception.py:151 msgid "Attempted to authenticate with an unsupported method." msgstr "" #: keystone/exception.py:159 msgid "Additional authentications steps required." msgstr "" #: keystone/exception.py:167 msgid "You are not authorized to perform the requested action." msgstr "" #: keystone/exception.py:174 #, python-format msgid "You are not authorized to perform the requested action, %(action)s." msgstr "" #: keystone/exception.py:179 #, python-format msgid "Could not change immutable attribute %(attribute)s in target %(target)s" msgstr "" #: keystone/exception.py:184 #, python-format msgid "Could not find, %(target)s." msgstr "" #: keystone/exception.py:190 #, python-format msgid "Could not find endpoint, %(endpoint_id)s." msgstr "" #: keystone/exception.py:197 msgid "An unhandled exception has occurred: Could not find metadata." msgstr "" #: keystone/exception.py:202 #, python-format msgid "Could not find policy, %(policy_id)s." msgstr "" #: keystone/exception.py:206 #, python-format msgid "Could not find role, %(role_id)s." msgstr "" #: keystone/exception.py:210 #, python-format msgid "Could not find region, %(region_id)s." msgstr "" #: keystone/exception.py:214 #, python-format msgid "Could not find service, %(service_id)s." msgstr "" #: keystone/exception.py:218 #, python-format msgid "Could not find domain, %(domain_id)s." msgstr "" #: keystone/exception.py:222 #, python-format msgid "Could not find project, %(project_id)s." msgstr "" #: keystone/exception.py:226 #, python-format msgid "Could not find token, %(token_id)s." msgstr "" #: keystone/exception.py:230 #, python-format msgid "Could not find user, %(user_id)s." msgstr "" #: keystone/exception.py:234 #, python-format msgid "Could not find group, %(group_id)s." msgstr "" #: keystone/exception.py:238 #, python-format msgid "Could not find mapping, %(mapping_id)s." msgstr "" #: keystone/exception.py:242 #, python-format msgid "Could not find trust, %(trust_id)s." msgstr "" #: keystone/exception.py:246 #, python-format msgid "No remaining uses for trust %(trust_id)s." msgstr "" #: keystone/exception.py:250 #, python-format msgid "Could not find credential, %(credential_id)s." msgstr "" #: keystone/exception.py:254 #, python-format msgid "Could not find version, %(version)s." msgstr "" #: keystone/exception.py:258 #, python-format msgid "Could not find IdentityProvider, %(idp_id)s." msgstr "" #: keystone/exception.py:262 #, python-format msgid "" "Could not find federated protocol %(protocol_id)s for IdentityProvider, " "%(idp_id)s" msgstr "" #: keystone/exception.py:267 #, python-format msgid "Conflict occurred attempting to store %(type)s. %(details)s" msgstr "" #: keystone/exception.py:274 msgid "Request is too large." msgstr "" #: keystone/exception.py:281 msgid "An unexpected error prevented the server from fulfilling your request." msgstr "" #: keystone/exception.py:284 #, python-format msgid "" "An unexpected error prevented the server from fulfilling your request. " "%(exception)s" msgstr "" #: keystone/exception.py:307 msgid "" "Expected signing certificates are not available on the server. Please " "check Keystone configuration." msgstr "" #: keystone/exception.py:313 #, python-format msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details." msgstr "" #: keystone/exception.py:318 #, python-format msgid "" "Group %(group_id)s returned by mapping %(mapping_id)s was not found in " "the backend." msgstr "" #: keystone/exception.py:323 msgid "The action you have requested has not been implemented." msgstr "" #: keystone/exception.py:330 msgid "The service you have requested is no longer available on this server." msgstr "" #: keystone/exception.py:337 #, python-format msgid "The Keystone configuration file %(config_file)s could not be found." msgstr "" #: keystone/exception.py:343 #, python-format msgid "" "%(mod_name)s doesn't provide database migrations. The migration " "repository path at %(path)s doesn't exist or isn't a directory." msgstr "" #: keystone/notifications.py:120 #, python-format msgid "%(event)s is not a valid notification event, must be one of: %(actions)s" msgstr "" #: keystone/notifications.py:129 #, python-format msgid "Method not callable: %s" msgstr "" #: keystone/notifications.py:137 #, python-format msgid "Callback: `%(callback)s` subscribed to event `%(event)s`." msgstr "" #: keystone/notifications.py:156 #, python-format msgid "" "Invoking callback %(cb_name)s for event %(service)s %(resource_type)s " "%(operation)s for%(payload)s" msgstr "" #: keystone/notifications.py:219 #, python-format msgid "Failed to send %(res_id)s %(event_type)s notification" msgstr "" #: keystone/notifications.py:290 #, python-format msgid "CADF Event: %s" msgstr "" #: keystone/notifications.py:303 #, python-format msgid "Failed to send %(action)s %(event_type)s notification" msgstr "" #: keystone/assignment/controllers.py:72 #, python-format msgid "Authentication failed: %s" msgstr "" #: keystone/assignment/controllers.py:106 #: keystone/assignment/controllers.py:220 keystone/identity/controllers.py:131 msgid "Name field is required and cannot be empty" msgstr "" #: keystone/assignment/controllers.py:143 #, python-format msgid "User %(user_id)s in project %(project_id)s doesn't exist." msgstr "" #: keystone/assignment/controllers.py:161 msgid "Marker could not be found" msgstr "" #: keystone/assignment/controllers.py:172 msgid "Invalid limit value" msgstr "" #: keystone/assignment/controllers.py:475 msgid "Specify a domain or project, not both" msgstr "" #: keystone/assignment/controllers.py:480 msgid "Specify a user or group, not both" msgstr "" #: keystone/assignment/controllers.py:694 #, python-format msgid "" "Group %(group)s not found for role-assignment - %(target)s with Role: " "%(role)s" msgstr "" #: keystone/assignment/core.py:242 #, python-format msgid "Creating the default role %s because it does not exist." msgstr "" #: keystone/assignment/core.py:274 #, python-format msgid "Removing role %s failed because it does not exist." msgstr "" #: keystone/assignment/core.py:336 msgid "delete the default domain" msgstr "" #: keystone/assignment/core.py:347 msgid "cannot delete a domain that is enabled, please disable it first." msgstr "" #: keystone/assignment/core.py:384 #, python-format msgid "" "Project %(projectid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:397 #, python-format msgid "" "Group %(groupid)s not found when deleting domain contents for " "%(domainid)s, continuing with cleanup." msgstr "" #: keystone/assignment/core.py:409 #, python-format msgid "" "User %(userid)s not found when deleting domain contents for %(domainid)s," " continuing with cleanup." msgstr "" #: keystone/assignment/core.py:521 #, python-format msgid "Group %s not found, no tokens to invalidate." msgstr "" #: keystone/assignment/core.py:559 #, python-format msgid "Project (%s)" msgstr "" #: keystone/assignment/core.py:561 #, python-format msgid "Domain (%s)" msgstr "" #: keystone/assignment/core.py:563 msgid "Unknown Target" msgstr "" #: keystone/assignment/core.py:564 #, python-format msgid "" "Group (%(group)s), referenced in assignment for %(target)s, not found - " "ignoring." msgstr "" #: keystone/assignment/core.py:1005 keystone/common/controller.py:269 #: keystone/identity/core.py:232 #, python-format msgid "Expected dict or list: %s" msgstr "" #: keystone/assignment/backends/kvs.py:202 #: keystone/assignment/backends/ldap.py:581 #: keystone/assignment/backends/sql.py:353 #, python-format msgid "Cannot remove role that has not been granted, %s" msgstr "" #: keystone/assignment/backends/ldap.py:111 msgid "Domain metadata not supported by LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:200 #: keystone/assignment/backends/ldap.py:248 keystone/common/ldap/core.py:334 #: keystone/identity/backends/kvs.py:117 keystone/identity/backends/kvs.py:224 #, python-format msgid "Duplicate ID, %s." msgstr "" #: keystone/assignment/backends/ldap.py:208 keystone/common/ldap/core.py:324 #: keystone/identity/backends/kvs.py:125 keystone/identity/backends/kvs.py:152 #: keystone/identity/backends/kvs.py:231 keystone/identity/backends/kvs.py:259 #, python-format msgid "Duplicate name, %s." msgstr "" #: keystone/assignment/backends/ldap.py:250 #: keystone/assignment/backends/ldap.py:258 #: keystone/assignment/backends/ldap.py:262 msgid "Domains are read-only against LDAP" msgstr "" #: keystone/assignment/backends/ldap.py:315 #: keystone/assignment/backends/sql.py:137 msgid "Inherited roles can only be assigned to domains" msgstr "" #: keystone/assignment/backends/ldap.py:554 #, python-format msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s" msgstr "" #: keystone/assignment/backends/ldap.py:560 #, python-format msgid "Role %s not found" msgstr "" #: keystone/assignment/backends/ldap.py:667 #, python-format msgid "Cannot duplicate name %s" msgstr "" #: keystone/assignment/backends/sql.py:124 #, python-format msgid "" "Unexpected combination of grant attributes - User, Group, Project, " "Domain: %s" msgstr "" #: keystone/assignment/backends/sql.py:293 msgid "Must specify either domain or project" msgstr "" #: keystone/assignment/backends/sql.py:374 #, python-format msgid "Unexpected assignment type encountered, %s" msgstr "" #: keystone/auth/controllers.py:57 #, python-format msgid "" "Cannot load an auth-plugin by class-name without a \"method\" attribute " "defined: %s" msgstr "" #: keystone/auth/controllers.py:65 #, python-format msgid "Driver requested method %(req)s does not match plugin name %(plugin)s." msgstr "" #: keystone/auth/controllers.py:70 #, python-format msgid "Auth Plugin %s does not have a \"method\" attribute." msgstr "" #: keystone/auth/controllers.py:74 #, python-format msgid "" "Auth plugin %(plugin)s is requesting previously registered method " "%(method)s" msgstr "" #: keystone/auth/controllers.py:115 #, python-format msgid "Project is disabled: %s" msgstr "" #: keystone/auth/controllers.py:121 keystone/auth/plugins/password.py:41 #: keystone/token/core.py:80 keystone/token/core.py:96 #, python-format msgid "Domain is disabled: %s" msgstr "" #: keystone/auth/controllers.py:278 msgid "Scoping to both domain and project is not allowed" msgstr "" #: keystone/auth/controllers.py:281 msgid "Scoping to both domain and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:284 msgid "Scoping to both project and trust is not allowed" msgstr "" #: keystone/auth/controllers.py:380 #, python-format msgid "" "User %(user_id)s doesn't have access to default project %(project_id)s. " "The token will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:387 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s is disabled. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:396 #, python-format msgid "" "User %(user_id)s's default project %(project_id)s not found. The token " "will be unscoped rather than scoped to the project." msgstr "" #: keystone/auth/controllers.py:427 msgid "User not found" msgstr "" #: keystone/auth/plugins/external.py:46 msgid "No authenticated user" msgstr "" #: keystone/auth/plugins/external.py:56 #, python-format msgid "Unable to lookup user %s" msgstr "" #: keystone/auth/plugins/oauth1.py:38 #, python-format msgid "%s not supported" msgstr "" #: keystone/auth/plugins/oauth1.py:56 msgid "Access token is expired" msgstr "" #: keystone/auth/plugins/oauth1.py:70 msgid "Could not validate the access token" msgstr "" #: keystone/auth/plugins/password.py:47 keystone/token/core.py:72 #, python-format msgid "User is disabled: %s" msgstr "" #: keystone/auth/plugins/password.py:123 msgid "Invalid username or password" msgstr "" #: keystone/auth/plugins/saml2.py:95 msgid "Federation token is expired" msgstr "" #: keystone/catalog/controllers.py:154 #, python-format msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\"" msgstr "" #: keystone/catalog/controllers.py:206 keystone/catalog/controllers.py:265 #: keystone/identity/controllers.py:134 msgid "Enabled field must be a boolean" msgstr "" #: keystone/catalog/core.py:42 #, python-format msgid "Malformed endpoint %(url)s - unknown key %(keyerror)s" msgstr "" #: keystone/catalog/core.py:47 #, python-format msgid "" "Malformed endpoint %(url)s - unknown key %(keyerror)s(are you missing " "brackets ?)" msgstr "" #: keystone/catalog/core.py:53 #, python-format msgid "" "Malformed endpoint %s - incomplete format (are you missing a type " "notifier ?)" msgstr "" #: keystone/catalog/backends/templated.py:106 #, python-format msgid "Unable to open template file %s" msgstr "" #: keystone/common/authorization.py:75 msgid "RBAC: Invalid user data in v3 token" msgstr "" #: keystone/common/authorization.py:80 msgid "RBAC: Proceeding without project" msgstr "" #: keystone/common/authorization.py:99 msgid "RBAC: Invalid user data in v2 token" msgstr "" #: keystone/common/authorization.py:104 msgid "RBAC: Proceeding without tenant" msgstr "" #: keystone/common/base64utils.py:205 keystone/common/base64utils.py:278 #: keystone/common/base64utils.py:332 msgid "pad must be single character" msgstr "" #: keystone/common/base64utils.py:211 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char" msgstr "" #: keystone/common/base64utils.py:215 #, python-format msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char" msgstr "" #: keystone/common/base64utils.py:221 #, python-format msgid "text is not a multiple of 4, but contains pad \"%s\"" msgstr "" #: keystone/common/base64utils.py:240 keystone/common/base64utils.py:261 msgid "padded base64url text must be multiple of 4 characters" msgstr "" #: keystone/common/controller.py:39 #, python-format msgid "RBAC: Authorizing %(action)s(%(kwargs)s)" msgstr "" #: keystone/common/controller.py:46 msgid "RBAC: using auth context from the request environment" msgstr "" #: keystone/common/controller.py:51 msgid "RBAC: building auth context from the incoming auth token" msgstr "" #: keystone/common/controller.py:62 keystone/middleware/core.py:266 msgid "RBAC: Invalid token" msgstr "" #: keystone/common/controller.py:91 keystone/common/controller.py:182 #: keystone/common/controller.py:585 msgid "RBAC: Bypassing authorization" msgstr "" #: keystone/common/controller.py:138 keystone/common/controller.py:180 #: keystone/common/controller.py:603 msgid "RBAC: Authorization granted" msgstr "" #: keystone/common/controller.py:168 #, python-format msgid "RBAC: Adding query filter params (%s)" msgstr "" #: keystone/common/controller.py:532 msgid "Cannot change Domain ID" msgstr "" #: keystone/common/controller.py:556 msgid "Invalid token in _get_domain_id_for_request" msgstr "" #: keystone/common/dependency.py:83 msgid "event_callbacks must be a dict" msgstr "" #: keystone/common/dependency.py:88 #, python-format msgid "event_callbacks[%s] must be a dict" msgstr "" #: keystone/common/pemutils.py:223 #, python-format msgid "unknown pem_type \"%(pem_type)s\", valid types are: %(valid_pem_types)s" msgstr "" #: keystone/common/pemutils.py:242 #, python-format msgid "" "unknown pem header \"%(pem_header)s\", valid headers are: " "%(valid_pem_headers)s" msgstr "" #: keystone/common/pemutils.py:300 #, python-format msgid "failed to find end matching \"%s\"" msgstr "" #: keystone/common/pemutils.py:304 #, python-format msgid "" "beginning & end PEM headers do not match (%(begin_pem_header)s!= " "%(end_pem_header)s)" msgstr "" #: keystone/common/pemutils.py:379 #, python-format msgid "unknown pem_type: \"%s\"" msgstr "" #: keystone/common/pemutils.py:391 #, python-format msgid "" "failed to base64 decode %(pem_type)s PEM at position%(position)d: " "%(err_msg)s" msgstr "" #: keystone/common/serializer.py:203 msgid "Multiple truncation attributes found" msgstr "" #: keystone/common/utils.py:77 #, python-format msgid "Truncating user password to %s characters." msgstr "" #: keystone/common/utils.py:195 keystone/credential/controllers.py:42 msgid "Invalid blob in credential" msgstr "" #: keystone/common/utils.py:274 msgid "" "Error setting up the debug environment. Verify that the option --debug-" "url has the format : and that a debugger processes is " "listening on that port." msgstr "" #: keystone/common/wsgi.py:67 msgid "No bind information present in token" msgstr "" #: keystone/common/wsgi.py:71 #, python-format msgid "Named bind mode %s not in bind information" msgstr "" #: keystone/common/wsgi.py:78 msgid "Kerberos credentials required and not present" msgstr "" #: keystone/common/wsgi.py:82 msgid "Kerberos credentials do not match those in bind" msgstr "" #: keystone/common/wsgi.py:85 msgid "Kerberos bind authentication successful" msgstr "" #: keystone/common/wsgi.py:88 #, python-format msgid "Ignoring unknown bind for permissive mode: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:92 #, python-format msgid "Couldn't verify unknown bind: {%(bind_type)s: %(identifier)s}" msgstr "" #: keystone/common/wsgi.py:181 #, python-format msgid "arg_dict: %s" msgstr "" #: keystone/common/wsgi.py:210 #, python-format msgid "Authorization failed. %(exception)s from %(remote_addr)s" msgstr "" #: keystone/common/wsgi.py:287 #, python-format msgid "%s field is required and cannot be empty" msgstr "" #: keystone/common/wsgi.py:298 msgid "" "will not lookup trust as the request auth token is either absent or it is" " the system admin token" msgstr "" #: keystone/common/wsgi.py:305 msgid "Invalid token in _get_trust_id_for_request" msgstr "" #: keystone/common/wsgi.py:501 keystone/tests/test_wsgi.py:274 msgid "The resource could not be found." msgstr "" #: keystone/common/cache/core.py:54 #, python-format msgid "CACHE_GET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:60 #, python-format msgid "CACHE_GET_MULTI: \"%(keys)r\" Values: \"%(values)r\"" msgstr "" #: keystone/common/cache/core.py:65 #, python-format msgid "CACHE_SET: Key: \"%(key)r\" Value: \"%(value)r\"" msgstr "" #: keystone/common/cache/core.py:70 #, python-format msgid "CACHE_SET_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:75 #, python-format msgid "CACHE_DELETE: \"%r\"" msgstr "" #: keystone/common/cache/core.py:78 #, python-format msgid "CACHE_DELETE_MULTI: \"%r\"" msgstr "" #: keystone/common/cache/core.py:96 #, python-format msgid "" "Unable to build cache config-key. Expected format \":\". " "Skipping unknown format: %s" msgstr "" #: keystone/common/cache/core.py:104 #, python-format msgid "Keystone Cache Config: %s" msgstr "" #: keystone/common/cache/core.py:119 msgid "region not type dogpile.cache.CacheRegion" msgstr "" #: keystone/common/cache/core.py:152 #, python-format msgid "Adding cache-proxy '%s' to backend." msgstr "" #: keystone/common/cache/backends/mongo.py:231 msgid "db_hosts value is required" msgstr "" #: keystone/common/cache/backends/mongo.py:236 msgid "database db_name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:241 msgid "cache_collection name is required" msgstr "" #: keystone/common/cache/backends/mongo.py:252 msgid "integer value expected for w (write concern attribute)" msgstr "" #: keystone/common/cache/backends/mongo.py:260 msgid "replicaset_name required when use_replica is True" msgstr "" #: keystone/common/cache/backends/mongo.py:275 msgid "integer value expected for mongo_ttl_seconds" msgstr "" #: keystone/common/cache/backends/mongo.py:301 msgid "no ssl support available" msgstr "" #: keystone/common/cache/backends/mongo.py:310 #, python-format msgid "" "Invalid ssl_cert_reqs value of %s, must be one of \"NONE\", \"OPTIONAL\"," " \"REQUIRED\"" msgstr "" #: keystone/common/cache/backends/mongo.py:403 #, python-format msgid "" "TTL index already exists on db collection <%(c_name)s>, remove index " "<%(indx_name)s> first to make updated mongo_ttl_seconds value to be " "effective" msgstr "" #: keystone/common/environment/__init__.py:52 #, python-format msgid "Environment configured as: %s" msgstr "" #: keystone/common/environment/eventlet_server.py:52 #, python-format msgid "Starting %(arg0)s on %(host)s:%(port)s" msgstr "" #: keystone/common/environment/eventlet_server.py:123 msgid "Server error" msgstr "" #: keystone/common/kvs/core.py:63 #, python-format msgid "Registering Dogpile Backend %(backend_path)s as %(backend_name)s" msgstr "" #: keystone/common/kvs/core.py:71 #, python-format msgid "Lock Timeout occurred for key, %(target)s" msgstr "" #: keystone/common/kvs/core.py:106 #, python-format msgid "KVS region %s is already configured. Cannot reconfigure." msgstr "" #: keystone/common/kvs/core.py:122 #, python-format msgid "Importing class %s as KVS proxy." msgstr "" #: keystone/common/kvs/core.py:130 #, python-format msgid "%s is not a dogpile.proxy.ProxyBackend" msgstr "" #: keystone/common/kvs/core.py:134 #, python-format msgid "Adding proxy '%(proxy)s' to KVS %(name)s." msgstr "" #: keystone/common/kvs/core.py:141 #, python-format msgid "Key Value Store not configured: %s" msgstr "" #: keystone/common/kvs/core.py:158 #, python-format msgid "" "Non-expiring keys not supported/required by %(region)s backend; unable to" " set key_mangler for backend: %(err)s" msgstr "" #: keystone/common/kvs/core.py:184 #, python-format msgid "Using %(func)s as KVS region %(name)s key_mangler" msgstr "" #: keystone/common/kvs/core.py:194 msgid "`key_mangler` option must be a function reference" msgstr "" #: keystone/common/kvs/core.py:196 #, python-format msgid "Using default dogpile sha1_mangle_key as KVS region %s key_mangler" msgstr "" #: keystone/common/kvs/core.py:206 #, python-format msgid "KVS region %s key_mangler disabled." msgstr "" #: keystone/common/kvs/core.py:235 #, python-format msgid "KVS region configuration for %(name)s: %(config)r" msgstr "" #: keystone/common/kvs/core.py:348 #, python-format msgid "Lock key must match target key: %(lock)s != %(target)s" msgstr "" #: keystone/common/kvs/core.py:352 msgid "Must be called within an active lock context." msgstr "" #: keystone/common/kvs/core.py:376 #, python-format msgid "KVS lock acquired for: %s" msgstr "" #: keystone/common/kvs/core.py:395 #, python-format msgid "KVS lock released for: %s" msgstr "" #: keystone/common/kvs/core.py:397 #, python-format msgid "KVS lock released (timeout reached) for: %s" msgstr "" #: keystone/common/kvs/backends/memcached.py:72 #, python-format msgid "Maximum lock attempts on %s occurred." msgstr "" #: keystone/common/kvs/backends/memcached.py:111 #, python-format msgid "" "Backend `%(driver)s` is not a valid memcached backend. Valid drivers: " "%(driver_list)s" msgstr "" #: keystone/common/kvs/backends/memcached.py:182 msgid "`key_mangler` functions must be callable." msgstr "" #: keystone/common/ldap/core.py:77 #, python-format msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:87 #, python-format msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:99 #, python-format msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s" msgstr "" #: keystone/common/ldap/core.py:216 #, python-format msgid "" "Invalid additional attribute mapping: \"%s\". Format must be " ":" msgstr "" #: keystone/common/ldap/core.py:222 #, python-format msgid "" "Invalid additional attribute mapping: \"%(item)s\". Value " "\"%(attr_map)s\" must use one of %(keys)s." msgstr "" #: keystone/common/ldap/core.py:303 #, python-format msgid "LDAP %s create" msgstr "" #: keystone/common/ldap/core.py:308 #, python-format msgid "LDAP %s update" msgstr "" #: keystone/common/ldap/core.py:313 #, python-format msgid "LDAP %s delete" msgstr "" #: keystone/common/ldap/core.py:434 #, python-format msgid "Cannot change %(option_name)s %(attr)s" msgstr "" #: keystone/common/ldap/core.py:491 #, python-format msgid "LDAP init: url=%s" msgstr "" #: keystone/common/ldap/core.py:492 #, python-format msgid "" "LDAP init: use_tls=%(use_tls)s\n" "tls_cacertfile=%(tls_cacertfile)s\n" "tls_cacertdir=%(tls_cacertdir)s\n" "tls_req_cert=%(tls_req_cert)s\n" "tls_avail=%(tls_avail)s\n" msgstr "" #: keystone/common/ldap/core.py:511 msgid "Invalid TLS / LDAPS combination" msgstr "" #: keystone/common/ldap/core.py:515 #, python-format msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available" msgstr "" #: keystone/common/ldap/core.py:525 #, python-format msgid "tls_cacertfile %s not found or is not a file" msgstr "" #: keystone/common/ldap/core.py:537 #, python-format msgid "tls_cacertdir %s not found or is not a directory" msgstr "" #: keystone/common/ldap/core.py:544 #, python-format msgid "LDAP TLS: invalid TLS_REQUIRE_CERT Option=%s" msgstr "" #: keystone/common/ldap/core.py:561 #, python-format msgid "LDAP bind: dn=%s" msgstr "" #: keystone/common/ldap/core.py:575 #, python-format msgid "LDAP add: dn=%(dn)s, attrs=%(attrs)s" msgstr "" #: keystone/common/ldap/core.py:586 #, python-format msgid "" "LDAP search: dn=%(dn)s, scope=%(scope)s, query=%(query)s, " "attrs=%(attrlist)s" msgstr "" #: keystone/common/ldap/core.py:610 msgid "" "Referrals were returned and ignored. Enable referral chasing in " "keystone.conf via [ldap] chase_referrals" msgstr "" #: keystone/common/ldap/core.py:650 msgid "" "LDAP Server does not support paging. Disable paging in keystone.conf to " "avoid this message." msgstr "" #: keystone/common/ldap/core.py:666 #, python-format msgid "LDAP modify: dn=%(dn)s, modlist=%(modlist)s" msgstr "" #: keystone/common/ldap/core.py:672 #, python-format msgid "LDAP delete: dn=%s" msgstr "" #: keystone/common/ldap/core.py:677 #, python-format msgid "LDAP delete_ext: dn=%(dn)s, serverctrls=%(serverctrls)s" msgstr "" #: keystone/common/sql/core.py:219 msgid "" "Cannot truncate a driver call without hints list as first parameter after" " self " msgstr "" #: keystone/common/sql/migration_helpers.py:125 #: keystone/common/sql/migration_helpers.py:150 #, python-format msgid "%s extension does not exist." msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:60 #, python-format msgid "" "Credential %(access)s already exists with different secret in %(table)s " "table" msgstr "" #: keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py:70 #, python-format msgid "" "Credential %(access)s already exists with different project in %(table)s " "table" msgstr "" #: keystone/contrib/ec2/controllers.py:305 msgid "Token belongs to another user" msgstr "" #: keystone/contrib/ec2/controllers.py:333 msgid "Credential belongs to another user" msgstr "" #: keystone/contrib/endpoint_filter/backends/sql.py:54 #, python-format msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s" msgstr "" #: keystone/contrib/example/core.py:64 keystone/contrib/example/core.py:73 #, python-format msgid "" "Received the following notification: service %(service)s, resource_type: " "%(resource_type)s, operation %(operation)s payload %(payload)s" msgstr "" #: keystone/contrib/federation/utils.py:198 msgid "Could not map user" msgstr "" #: keystone/contrib/federation/utils.py:227 #, python-format msgid "Ignoring user name %s" msgstr "" #: keystone/contrib/oauth1/controllers.py:79 msgid "Cannot change consumer secret" msgstr "" #: keystone/contrib/oauth1/controllers.py:153 #: keystone/contrib/oauth1/backends/sql.py:285 msgid "User IDs do not match" msgstr "" #: keystone/contrib/oauth1/controllers.py:160 msgid "Could not find role" msgstr "" #: keystone/contrib/oauth1/controllers.py:203 msgid "Invalid signature" msgstr "" #: keystone/contrib/oauth1/controllers.py:252 #: keystone/contrib/oauth1/controllers.py:322 msgid "Request token is expired" msgstr "" #: keystone/contrib/oauth1/controllers.py:266 msgid "There should not be any non-oauth parameters" msgstr "" #: keystone/contrib/oauth1/controllers.py:270 msgid "provided consumer key does not match stored consumer key" msgstr "" #: keystone/contrib/oauth1/controllers.py:274 msgid "provided verifier does not match stored verifier" msgstr "" #: keystone/contrib/oauth1/controllers.py:278 msgid "provided request key does not match stored request key" msgstr "" #: keystone/contrib/oauth1/controllers.py:282 msgid "Request Token does not have an authorizing user id" msgstr "" #: keystone/contrib/oauth1/controllers.py:338 msgid "authorizing user does not have role required" msgstr "" #: keystone/contrib/oauth1/controllers.py:353 msgid "User is not a member of the requested project" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:95 msgid "Consumer not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:199 msgid "Request token not found" msgstr "" #: keystone/contrib/oauth1/backends/sql.py:265 msgid "Access token not found" msgstr "" #: keystone/contrib/revoke/controllers.py:32 #, python-format msgid "invalid date format %s" msgstr "" #: keystone/contrib/revoke/core.py:173 keystone/token/provider.py:125 #: keystone/token/provider.py:146 keystone/token/provider.py:224 #: keystone/token/provider.py:231 keystone/token/providers/common.py:624 msgid "Failed to validate token" msgstr "" #: keystone/credential/core.py:120 #, python-format msgid "Deletion of credential is not required: %s" msgstr "" #: keystone/identity/controllers.py:161 msgid "Enabled field should be a boolean" msgstr "" #: keystone/identity/controllers.py:202 #, python-format msgid "Unable to remove user %(user)s from %(tenant)s." msgstr "" #: keystone/identity/controllers.py:221 #, python-format msgid "Unable to add user %(user)s to %(tenant)s." msgstr "" #: keystone/identity/core.py:105 #, python-format msgid "Invalid domain name (%s) found in config file name" msgstr "" #: keystone/identity/core.py:129 #, python-format msgid "Unable to locate domain config directory: %s" msgstr "" #: keystone/identity/core.py:142 #, python-format msgid "Ignoring file (%s) while scanning domain config directory" msgstr "" #: keystone/identity/core.py:183 msgid "" "Running an experimental and unsupported configuration " "(domain_specific_drivers_enabled = True); this will result in known " "issues." msgstr "" #: keystone/identity/backends/kvs.py:72 keystone/identity/backends/kvs.py:74 #: keystone/identity/backends/ldap.py:57 keystone/identity/backends/ldap.py:59 #: keystone/identity/backends/ldap.py:65 keystone/identity/backends/ldap.py:67 #: keystone/identity/backends/sql.py:112 keystone/identity/backends/sql.py:114 msgid "Invalid user / password" msgstr "" #: keystone/identity/backends/kvs.py:178 keystone/identity/backends/kvs.py:187 #: keystone/identity/backends/sql.py:198 keystone/identity/backends/sql.py:209 msgid "User not found in group" msgstr "" #: keystone/identity/backends/ldap.py:96 keystone/identity/backends/sql.py:160 msgid "Cannot change user ID" msgstr "" #: keystone/identity/backends/ldap.py:99 msgid "Cannot change user name" msgstr "" #: keystone/identity/backends/ldap.py:167 #, python-format msgid "" "Group member '%(user_dn)s' not found in '%(group_id)s'. The user should " "be removed from the group. The user will be ignored." msgstr "" #: keystone/identity/backends/ldap.py:308 #, python-format msgid "User %(user_id)s is already a member of group %(group_id)s" msgstr "" #: keystone/middleware/core.py:271 msgid "Auth token not in the request header. Will not build auth context." msgstr "" #: keystone/middleware/core.py:276 msgid "Auth context already exists in the request environment" msgstr "" #: keystone/middleware/core.py:281 #, python-format msgid "RBAC: auth_context: %s" msgstr "" #: keystone/openstack/common/eventlet_backdoor.py:140 #, python-format msgid "Eventlet backdoor listening on %(port)s for process %(pid)d" msgstr "" #: keystone/openstack/common/exception.py:103 msgid "Uncaught exception" msgstr "" #: keystone/openstack/common/excutils.py:62 #, python-format msgid "Original exception being dropped: %s" msgstr "" #: keystone/openstack/common/excutils.py:91 #, python-format msgid "Unexpected exception occurred %d time(s)... retrying." msgstr "" #: keystone/openstack/common/fileutils.py:63 #, python-format msgid "Reloading cached file %s" msgstr "" #: keystone/openstack/common/gettextutils.py:297 msgid "Message objects do not support addition." msgstr "" #: keystone/openstack/common/gettextutils.py:306 msgid "" "Message objects do not support str() because they may contain non-ascii " "characters. Please use unicode() or translate() instead." msgstr "" #: keystone/openstack/common/lockutils.py:103 #, python-format msgid "Could not release the acquired lock `%s`" msgstr "" #: keystone/openstack/common/lockutils.py:168 #, python-format msgid "Got semaphore \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:177 #, python-format msgid "Attempting to grab file lock \"%(lock)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:187 #, python-format msgid "Created lock path: %s" msgstr "" #: keystone/openstack/common/lockutils.py:205 #, python-format msgid "Got file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:209 #, python-format msgid "Released file lock \"%(lock)s\" at %(path)s" msgstr "" #: keystone/openstack/common/lockutils.py:247 #, python-format msgid "Got semaphore / lock \"%(function)s\"" msgstr "" #: keystone/openstack/common/lockutils.py:251 #, python-format msgid "Semaphore / lock released \"%(function)s\"" msgstr "" #: keystone/openstack/common/log.py:326 #, python-format msgid "Deprecated: %s" msgstr "" #: keystone/openstack/common/log.py:437 #, python-format msgid "Error loading logging config %(log_config)s: %(err_msg)s" msgstr "" #: keystone/openstack/common/log.py:488 #, python-format msgid "syslog facility must be one of: %s" msgstr "" #: keystone/openstack/common/log.py:709 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" #: keystone/openstack/common/loopingcall.py:82 #, python-format msgid "task run outlasted interval by %s sec" msgstr "" #: keystone/openstack/common/loopingcall.py:89 msgid "in fixed duration looping call" msgstr "" #: keystone/openstack/common/loopingcall.py:129 #, python-format msgid "Dynamic looping call sleeping for %.02f seconds" msgstr "" #: keystone/openstack/common/loopingcall.py:136 msgid "in dynamic looping call" msgstr "" #: keystone/openstack/common/policy.py:75 msgid "JSON file containing policy" msgstr "" #: keystone/openstack/common/policy.py:78 msgid "Rule enforced when requested rule is not found" msgstr "" #: keystone/openstack/common/policy.py:92 #, python-format msgid "Policy doesn't allow %s to be performed." msgstr "" #: keystone/openstack/common/policy.py:182 #, python-format msgid "Rules must be an instance of dict or Rules, got %s instead" msgstr "" #: keystone/openstack/common/policy.py:212 msgid "Rules successfully reloaded" msgstr "" #: keystone/openstack/common/policy.py:258 #, python-format msgid "Rule %s will be now enforced" msgstr "" #: keystone/openstack/common/policy.py:273 #, python-format msgid "Rule [%s] doesn't exist" msgstr "" #: keystone/openstack/common/policy.py:481 #, python-format msgid "Failed to understand rule %s" msgstr "" #: keystone/openstack/common/policy.py:491 #, python-format msgid "No handler for matches of kind %s" msgstr "" #: keystone/openstack/common/policy.py:761 #, python-format msgid "Failed to understand rule %r" msgstr "" #: keystone/openstack/common/processutils.py:130 #, python-format msgid "Got unknown keyword args to utils.execute: %r" msgstr "" #: keystone/openstack/common/processutils.py:145 #, python-format msgid "Running cmd (subprocess): %s" msgstr "" #: keystone/openstack/common/processutils.py:169 #: keystone/openstack/common/processutils.py:241 #, python-format msgid "Result was %s" msgstr "" #: keystone/openstack/common/processutils.py:181 #, python-format msgid "%r failed. Retrying." msgstr "" #: keystone/openstack/common/processutils.py:220 #, python-format msgid "Running cmd (SSH): %s" msgstr "" #: keystone/openstack/common/processutils.py:222 msgid "Environment not supported over SSH" msgstr "" #: keystone/openstack/common/processutils.py:226 msgid "process_input not supported over SSH" msgstr "" #: keystone/openstack/common/service.py:134 #: keystone/openstack/common/service.py:346 msgid "Full set of CONF:" msgstr "" #: keystone/openstack/common/service.py:143 #: keystone/openstack/common/service.py:231 #, python-format msgid "Caught %s, exiting" msgstr "" #: keystone/openstack/common/service.py:155 msgid "Exception during rpc cleanup." msgstr "" #: keystone/openstack/common/service.py:200 msgid "Parent process has died unexpectedly, exiting" msgstr "" #: keystone/openstack/common/service.py:237 msgid "Unhandled exception" msgstr "" #: keystone/openstack/common/service.py:270 msgid "Forking too fast, sleeping" msgstr "" #: keystone/openstack/common/service.py:289 #, python-format msgid "Started child %d" msgstr "" #: keystone/openstack/common/service.py:299 #, python-format msgid "Starting %d workers" msgstr "" #: keystone/openstack/common/service.py:316 #, python-format msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" #: keystone/openstack/common/service.py:320 #, python-format msgid "Child %(pid)s exited with status %(code)d" msgstr "" #: keystone/openstack/common/service.py:324 #, python-format msgid "pid %d not in child list" msgstr "" #: keystone/openstack/common/service.py:354 #, python-format msgid "Caught %s, stopping children" msgstr "" #: keystone/openstack/common/service.py:372 #, python-format msgid "Waiting on %d children to exit" msgstr "" #: keystone/openstack/common/strutils.py:86 #, python-format msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s" msgstr "" #: keystone/openstack/common/strutils.py:188 #, python-format msgid "Invalid string format: %s" msgstr "" #: keystone/openstack/common/strutils.py:195 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" #: keystone/openstack/common/versionutils.py:69 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s in favor of %(in_favor_of)s and " "may be removed in %(remove_in)s." msgstr "" #: keystone/openstack/common/versionutils.py:73 #, python-format msgid "" "%(what)s is deprecated as of %(as_of)s and may be removed in " "%(remove_in)s. It will not be superseded." msgstr "" #: keystone/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:188 msgid "version should be an integer" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:216 #, python-format msgid "" "Tables \"%s\" have non utf8 collation, please make sure all tables are " "CHARSET=utf8" msgstr "" #: keystone/openstack/common/db/sqlalchemy/migration.py:240 msgid "" "The database is not under version control, but has tables. Please stamp " "the current version of the schema manually." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:58 msgid "Sort key supplied was not valid." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:119 msgid "Unknown sort direction, must be 'desc' or 'asc'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:162 #, python-format msgid "" "There is no `deleted` column in `%s` table. Project doesn't use soft-" "deleted feature." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:174 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:181 #, python-format msgid "There is no `project_id` column in `%s` table." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:243 msgid "model should be a subclass of ModelBase" msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:286 #, python-format msgid "" "Please specify column %s in col_name_col_instance param. It is required " "because column has unsupported type by sqlite)." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:292 #, python-format msgid "" "col_name_col_instance param has wrong type of column instance for column " "%s It should be instance of sqlalchemy.Column." msgstr "" #: keystone/openstack/common/db/sqlalchemy/utils.py:400 msgid "Unsupported id columns type" msgstr "" #: keystone/policy/backends/rules.py:99 #, python-format msgid "enforce %(action)s: %(credentials)s" msgstr "" #: keystone/tests/core.py:162 #, python-format msgid "Failed to checkout %s" msgstr "" #: keystone/tests/fakeldap.py:250 #, python-format msgid "FakeLdap delete item: dn=%s" msgstr "" #: keystone/token/controllers.py:363 #, python-format msgid "User %(u_id)s is unauthorized for tenant %(t_id)s" msgstr "" #: keystone/token/controllers.py:380 keystone/token/controllers.py:383 msgid "Token does not belong to specified tenant." msgstr "" #: keystone/token/core.py:87 #, python-format msgid "Tenant is disabled: %s" msgstr "" #: keystone/token/provider.py:88 msgid "" "keystone.conf [signing] token_format (deprecated) conflicts with " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:96 msgid "" "keystone.conf [signing] token_format is deprecated in favor of " "keystone.conf [token] provider" msgstr "" #: keystone/token/provider.py:106 msgid "" "Unrecognized keystone.conf [signing] token_format: expected either 'UUID'" " or 'PKI'" msgstr "" #: keystone/token/provider.py:222 #, python-format msgid "Unexpected error or malformed token determining token expiry: %s" msgstr "" #: keystone/token/backends/kvs.py:56 msgid "" "It is recommended to only use the base key-value-store implementation for" " the token driver for testing purposes. Please use " "keystone.token.backends.memcache.Token or " "keystone.token.backends.sql.Token instead." msgstr "" #: keystone/token/backends/kvs.py:131 #, python-format msgid "Unknown token version %s" msgstr "" #: keystone/token/backends/kvs.py:170 #, python-format msgid "Token `%(token_id)s` is expired, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:179 #, python-format msgid "Token `%(token_id)s` is revoked, removing from `%(user_key)s`." msgstr "" #: keystone/token/backends/kvs.py:204 #, python-format msgid "Token `%s` is expired, not adding to the revocation list." msgstr "" #: keystone/token/backends/kvs.py:224 #, python-format msgid "" "Reinitializing revocation list due to error in loading revocation list " "from backend. Expected `list` type got `%(type)s`. Old revocation list " "data: %(list)r" msgstr "" #: keystone/token/backends/kvs.py:238 #, python-format msgid "" "Removing `%s` from revocation list due to invalid expires data in " "revocation list." msgstr "" #: keystone/token/backends/kvs.py:269 #, python-format msgid "" "Invalid token entry expected tuple of `(, )` got: " "`%(item)r`" msgstr "" #: keystone/token/backends/kvs.py:278 #, python-format msgid "Invalid expires time on token `%(token_id)s`: %(expires)r" msgstr "" #: keystone/token/providers/common.py:183 #: keystone/token/providers/common.py:286 #, python-format msgid "User %(user_id)s has no access to project %(project_id)s" msgstr "" #: keystone/token/providers/common.py:188 #: keystone/token/providers/common.py:291 #, python-format msgid "User %(user_id)s has no access to domain %(domain_id)s" msgstr "" #: keystone/token/providers/common.py:213 msgid "Trustor is disabled." msgstr "" #: keystone/token/providers/common.py:277 msgid "Trustee has no delegated roles." msgstr "" #: keystone/token/providers/common.py:341 msgid "User is not a trustee." msgstr "" #: keystone/token/providers/common.py:436 msgid "Oauth is disabled." msgstr "" #: keystone/token/providers/common.py:549 msgid "Non-default domain is not supported" msgstr "" #: keystone/token/providers/common.py:557 msgid "Domain scoped token is not supported" msgstr "" #: keystone/token/providers/pki.py:42 msgid "Unable to sign token" msgstr "" #: keystone/token/providers/pki.py:43 msgid "Unable to sign token." msgstr "" #: keystone/trust/controllers.py:140 msgid "At least one role should be specified." msgstr "" #: keystone/trust/core.py:58 msgid "remaining_uses must be a positive integer or null." msgstr "" keystone-2014.1/keystone/openstack/0000775000175400017540000000000012323716511020431 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/0000775000175400017540000000000012323716511021721 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/fileutils.py0000664000175400017540000000752212323716267024311 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import contextlib import errno import os import tempfile from keystone.openstack.common import excutils from keystone.openstack.common.gettextutils import _ # noqa from keystone.openstack.common import log as logging LOG = logging.getLogger(__name__) _FILE_CACHE = {} def ensure_tree(path): """Create a directory (and any ancestor directories required) :param path: Directory to create """ try: os.makedirs(path) except OSError as exc: if exc.errno == errno.EEXIST: if not os.path.isdir(path): raise else: raise def read_cached_file(filename, force_reload=False): """Read from a file if it has been modified. :param force_reload: Whether to reload the file. :returns: A tuple with a boolean specifying if the data is fresh or not. """ global _FILE_CACHE if force_reload and filename in _FILE_CACHE: del _FILE_CACHE[filename] reloaded = False mtime = os.path.getmtime(filename) cache_info = _FILE_CACHE.setdefault(filename, {}) if not cache_info or mtime > cache_info.get('mtime', 0): LOG.debug(_("Reloading cached file %s") % filename) with open(filename) as fap: cache_info['data'] = fap.read() cache_info['mtime'] = mtime reloaded = True return (reloaded, cache_info['data']) def delete_if_exists(path, remove=os.unlink): """Delete a file, but ignore file not found error. :param path: File to delete :param remove: Optional function to remove passed path """ try: remove(path) except OSError as e: if e.errno != errno.ENOENT: raise @contextlib.contextmanager def remove_path_on_error(path, remove=delete_if_exists): """Protect code that wants to operate on PATH atomically. Any exception will cause PATH to be removed. :param path: File to work with :param remove: Optional function to remove passed path """ try: yield except Exception: with excutils.save_and_reraise_exception(): remove(path) def file_open(*args, **kwargs): """Open file see built-in file() documentation for more details Note: The reason this is kept in a separate module is to easily be able to provide a stub module that doesn't alter system state at all (for unit tests) """ return file(*args, **kwargs) def write_to_tempfile(content, path=None, suffix='', prefix='tmp'): """Create temporary file or use existing file. This util is needed for creating temporary file with specified content, suffix and prefix. If path is not None, it will be used for writing content. If the path doesn't exist it'll be created. :param content: content for temporary file. :param path: same as parameter 'dir' for mkstemp :param suffix: same as parameter 'suffix' for mkstemp :param prefix: same as parameter 'prefix' for mkstemp For example: it can be used in database tests for creating configuration files. """ if path: ensure_tree(path) (fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix) try: os.write(fd, content) finally: os.close(fd) return path keystone-2014.1/keystone/openstack/common/network_utils.py0000664000175400017540000000517712323716267025226 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation. # All Rights Reserved. # # 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. """ Network-related utilities and helper functions. """ from keystone.openstack.common.py3kcompat import urlutils def parse_host_port(address, default_port=None): """Interpret a string as a host:port pair. An IPv6 address MUST be escaped if accompanied by a port, because otherwise ambiguity ensues: 2001:db8:85a3::8a2e:370:7334 means both [2001:db8:85a3::8a2e:370:7334] and [2001:db8:85a3::8a2e:370]:7334. >>> parse_host_port('server01:80') ('server01', 80) >>> parse_host_port('server01') ('server01', None) >>> parse_host_port('server01', default_port=1234) ('server01', 1234) >>> parse_host_port('[::1]:80') ('::1', 80) >>> parse_host_port('[::1]') ('::1', None) >>> parse_host_port('[::1]', default_port=1234) ('::1', 1234) >>> parse_host_port('2001:db8:85a3::8a2e:370:7334', default_port=1234) ('2001:db8:85a3::8a2e:370:7334', 1234) """ if address[0] == '[': # Escaped ipv6 _host, _port = address[1:].split(']') host = _host if ':' in _port: port = _port.split(':')[1] else: port = default_port else: if address.count(':') == 1: host, port = address.split(':') else: # 0 means ipv4, >1 means ipv6. # We prohibit unescaped ipv6 addresses with port. host = address port = default_port return (host, None if port is None else int(port)) def urlsplit(url, scheme='', allow_fragments=True): """Parse a URL using urlparse.urlsplit(), splitting query and fragments. This function papers over Python issue9374 when needed. The parameters are the same as urlparse.urlsplit. """ scheme, netloc, path, query, fragment = urlutils.urlsplit( url, scheme, allow_fragments) if allow_fragments and '#' in path: path, fragment = path.split('#', 1) if '?' in path: path, query = path.split('?', 1) return urlutils.SplitResult(scheme, netloc, path, query, fragment) keystone-2014.1/keystone/openstack/common/threadgroup.py0000664000175400017540000000754512323716267024642 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import eventlet from eventlet import greenpool from eventlet import greenthread from keystone.openstack.common import log as logging from keystone.openstack.common import loopingcall LOG = logging.getLogger(__name__) def _thread_done(gt, *args, **kwargs): """Callback function to be passed to GreenThread.link() when we spawn() Calls the :class:`ThreadGroup` to notify if. """ kwargs['group'].thread_done(kwargs['thread']) class Thread(object): """Wrapper around a greenthread, that holds a reference to the :class:`ThreadGroup`. The Thread will notify the :class:`ThreadGroup` when it has done so it can be removed from the threads list. """ def __init__(self, thread, group): self.thread = thread self.thread.link(_thread_done, group=group, thread=self) def stop(self): self.thread.kill() def wait(self): return self.thread.wait() def link(self, func, *args, **kwargs): self.thread.link(func, *args, **kwargs) class ThreadGroup(object): """The point of the ThreadGroup classis to: * keep track of timers and greenthreads (making it easier to stop them when need be). * provide an easy API to add timers. """ def __init__(self, thread_pool_size=10): self.pool = greenpool.GreenPool(thread_pool_size) self.threads = [] self.timers = [] def add_dynamic_timer(self, callback, initial_delay=None, periodic_interval_max=None, *args, **kwargs): timer = loopingcall.DynamicLoopingCall(callback, *args, **kwargs) timer.start(initial_delay=initial_delay, periodic_interval_max=periodic_interval_max) self.timers.append(timer) def add_timer(self, interval, callback, initial_delay=None, *args, **kwargs): pulse = loopingcall.FixedIntervalLoopingCall(callback, *args, **kwargs) pulse.start(interval=interval, initial_delay=initial_delay) self.timers.append(pulse) def add_thread(self, callback, *args, **kwargs): gt = self.pool.spawn(callback, *args, **kwargs) th = Thread(gt, self) self.threads.append(th) return th def thread_done(self, thread): self.threads.remove(thread) def stop(self): current = greenthread.getcurrent() for x in self.threads: if x is current: # don't kill the current thread. continue try: x.stop() except Exception as ex: LOG.exception(ex) for x in self.timers: try: x.stop() except Exception as ex: LOG.exception(ex) self.timers = [] def wait(self): for x in self.timers: try: x.wait() except eventlet.greenlet.GreenletExit: pass except Exception as ex: LOG.exception(ex) current = greenthread.getcurrent() for x in self.threads: if x is current: continue try: x.wait() except eventlet.greenlet.GreenletExit: pass except Exception as ex: LOG.exception(ex) keystone-2014.1/keystone/openstack/common/eventlet_backdoor.py0000664000175400017540000001130412323716267025774 0ustar jenkinsjenkins00000000000000# Copyright (c) 2012 OpenStack Foundation. # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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 errno import gc import os import pprint import socket import sys import traceback import eventlet import eventlet.backdoor import greenlet from oslo.config import cfg from keystone.openstack.common.gettextutils import _ # noqa from keystone.openstack.common import log as logging help_for_backdoor_port = ( "Acceptable values are 0, , and :, where 0 results " "in listening on a random tcp port number; results in listening " "on the specified port number (and not enabling backdoor if that port " "is in use); and : results in listening on the smallest " "unused port number within the specified range of port numbers. The " "chosen port is displayed in the service's log file.") eventlet_backdoor_opts = [ cfg.StrOpt('backdoor_port', default=None, help="Enable eventlet backdoor. %s" % help_for_backdoor_port) ] CONF = cfg.CONF CONF.register_opts(eventlet_backdoor_opts) LOG = logging.getLogger(__name__) class EventletBackdoorConfigValueError(Exception): def __init__(self, port_range, help_msg, ex): msg = ('Invalid backdoor_port configuration %(range)s: %(ex)s. ' '%(help)s' % {'range': port_range, 'ex': ex, 'help': help_msg}) super(EventletBackdoorConfigValueError, self).__init__(msg) self.port_range = port_range def _dont_use_this(): print("Don't use this, just disconnect instead") def _find_objects(t): return filter(lambda o: isinstance(o, t), gc.get_objects()) def _print_greenthreads(): for i, gt in enumerate(_find_objects(greenlet.greenlet)): print(i, gt) traceback.print_stack(gt.gr_frame) print() def _print_nativethreads(): for threadId, stack in sys._current_frames().items(): print(threadId) traceback.print_stack(stack) print() def _parse_port_range(port_range): if ':' not in port_range: start, end = port_range, port_range else: start, end = port_range.split(':', 1) try: start, end = int(start), int(end) if end < start: raise ValueError return start, end except ValueError as ex: raise EventletBackdoorConfigValueError(port_range, ex, help_for_backdoor_port) def _listen(host, start_port, end_port, listen_func): try_port = start_port while True: try: return listen_func((host, try_port)) except socket.error as exc: if (exc.errno != errno.EADDRINUSE or try_port >= end_port): raise try_port += 1 def initialize_if_enabled(): backdoor_locals = { 'exit': _dont_use_this, # So we don't exit the entire process 'quit': _dont_use_this, # So we don't exit the entire process 'fo': _find_objects, 'pgt': _print_greenthreads, 'pnt': _print_nativethreads, } if CONF.backdoor_port is None: return None start_port, end_port = _parse_port_range(str(CONF.backdoor_port)) # NOTE(johannes): The standard sys.displayhook will print the value of # the last expression and set it to __builtin__._, which overwrites # the __builtin__._ that gettext sets. Let's switch to using pprint # since it won't interact poorly with gettext, and it's easier to # read the output too. def displayhook(val): if val is not None: pprint.pprint(val) sys.displayhook = displayhook sock = _listen('localhost', start_port, end_port, eventlet.listen) # In the case of backdoor port being zero, a port number is assigned by # listen(). In any case, pull the port number out here. port = sock.getsockname()[1] LOG.info(_('Eventlet backdoor listening on %(port)s for process %(pid)d') % {'port': port, 'pid': os.getpid()}) eventlet.spawn_n(eventlet.backdoor.backdoor_server, sock, locals=backdoor_locals) return port keystone-2014.1/keystone/openstack/common/importutils.py0000664000175400017540000000421512323716267024700 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ Import related utilities and helper functions. """ import sys import traceback def import_class(import_str): """Returns a class from a string including module and class.""" mod_str, _sep, class_str = import_str.rpartition('.') try: __import__(mod_str) return getattr(sys.modules[mod_str], class_str) except (ValueError, AttributeError): raise ImportError('Class %s cannot be found (%s)' % (class_str, traceback.format_exception(*sys.exc_info()))) def import_object(import_str, *args, **kwargs): """Import a class and return an instance of it.""" return import_class(import_str)(*args, **kwargs) def import_object_ns(name_space, import_str, *args, **kwargs): """Tries to import object from default namespace. Imports a class and return an instance of it, first by trying to find the class in a default namespace, then failing back to a full path if not found in the default namespace. """ import_value = "%s.%s" % (name_space, import_str) try: return import_class(import_value)(*args, **kwargs) except ImportError: return import_class(import_str)(*args, **kwargs) def import_module(import_str): """Import a module.""" __import__(import_str) return sys.modules[import_str] def try_import(import_str, default=None): """Try to import a module and if it fails return default.""" try: return import_module(import_str) except ImportError: return default keystone-2014.1/keystone/openstack/common/strutils.py0000664000175400017540000001657412323716267024211 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # 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. """ System-level utilities and helper functions. """ import re import sys import unicodedata import six from keystone.openstack.common.gettextutils import _ # Used for looking up extensions of text # to their 'multiplied' byte amount BYTE_MULTIPLIERS = { '': 1, 't': 1024 ** 4, 'g': 1024 ** 3, 'm': 1024 ** 2, 'k': 1024, } BYTE_REGEX = re.compile(r'(^-?\d+)(\D*)') TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]") SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") def int_from_bool_as_string(subject): """Interpret a string as a boolean and return either 1 or 0. Any string value in: ('True', 'true', 'On', 'on', '1') is interpreted as a boolean True. Useful for JSON-decoded stuff and config file parsing """ return bool_from_string(subject) and 1 or 0 def bool_from_string(subject, strict=False, default=False): """Interpret a string as a boolean. A case-insensitive match is performed such that strings matching 't', 'true', 'on', 'y', 'yes', or '1' are considered True and, when `strict=False`, anything else returns the value specified by 'default'. Useful for JSON-decoded stuff and config file parsing. If `strict=True`, unrecognized values, including None, will raise a ValueError which is useful when parsing values passed in from an API call. Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. """ if not isinstance(subject, six.string_types): subject = str(subject) lowered = subject.strip().lower() if lowered in TRUE_STRINGS: return True elif lowered in FALSE_STRINGS: return False elif strict: acceptable = ', '.join( "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) msg = _("Unrecognized value '%(val)s', acceptable values are:" " %(acceptable)s") % {'val': subject, 'acceptable': acceptable} raise ValueError(msg) else: return default def safe_decode(text, incoming=None, errors='strict'): """Decodes incoming str using `incoming` if they're not already unicode. :param incoming: Text's current encoding :param errors: Errors handling policy. See here for valid values http://docs.python.org/2/library/codecs.html :returns: text or a unicode `incoming` encoded representation of it. :raises TypeError: If text is not an instance of str """ if not isinstance(text, six.string_types): raise TypeError("%s can't be decoded" % type(text)) if isinstance(text, six.text_type): return text if not incoming: incoming = (sys.stdin.encoding or sys.getdefaultencoding()) try: return text.decode(incoming, errors) except UnicodeDecodeError: # Note(flaper87) If we get here, it means that # sys.stdin.encoding / sys.getdefaultencoding # didn't return a suitable encoding to decode # text. This happens mostly when global LANG # var is not set correctly and there's no # default encoding. In this case, most likely # python will use ASCII or ANSI encoders as # default encodings but they won't be capable # of decoding non-ASCII characters. # # Also, UTF-8 is being used since it's an ASCII # extension. return text.decode('utf-8', errors) def safe_encode(text, incoming=None, encoding='utf-8', errors='strict'): """Encodes incoming str/unicode using `encoding`. If incoming is not specified, text is expected to be encoded with current python's default encoding. (`sys.getdefaultencoding`) :param incoming: Text's current encoding :param encoding: Expected encoding for text (Default UTF-8) :param errors: Errors handling policy. See here for valid values http://docs.python.org/2/library/codecs.html :returns: text or a bytestring `encoding` encoded representation of it. :raises TypeError: If text is not an instance of str """ if not isinstance(text, six.string_types): raise TypeError("%s can't be encoded" % type(text)) if not incoming: incoming = (sys.stdin.encoding or sys.getdefaultencoding()) if isinstance(text, six.text_type): if six.PY3: return text.encode(encoding, errors).decode(incoming) else: return text.encode(encoding, errors) elif text and encoding != incoming: # Decode text before encoding it with `encoding` text = safe_decode(text, incoming, errors) if six.PY3: return text.encode(encoding, errors).decode(incoming) else: return text.encode(encoding, errors) return text def to_bytes(text, default=0): """Converts a string into an integer of bytes. Looks at the last characters of the text to determine what conversion is needed to turn the input text into a byte number. Supports "B, K(B), M(B), G(B), and T(B)". (case insensitive) :param text: String input for bytes size conversion. :param default: Default return value when text is blank. """ match = BYTE_REGEX.search(text) if match: magnitude = int(match.group(1)) mult_key_org = match.group(2) if not mult_key_org: return magnitude elif text: msg = _('Invalid string format: %s') % text raise TypeError(msg) else: return default mult_key = mult_key_org.lower().replace('b', '', 1) multiplier = BYTE_MULTIPLIERS.get(mult_key) if multiplier is None: msg = _('Unknown byte multiplier: %s') % mult_key_org raise TypeError(msg) return magnitude * multiplier def to_slug(value, incoming=None, errors="strict"): """Normalize string. Convert to lowercase, remove non-word characters, and convert spaces to hyphens. Inspired by Django's `slugify` filter. :param value: Text to slugify :param incoming: Text's current encoding :param errors: Errors handling policy. See here for valid values http://docs.python.org/2/library/codecs.html :returns: slugified unicode representation of `value` :raises TypeError: If text is not an instance of str """ value = safe_decode(value, incoming, errors) # NOTE(aababilov): no need to use safe_(encode|decode) here: # encodings are always "ascii", error handling is always "ignore" # and types are always known (first: unicode; second: str) value = unicodedata.normalize("NFKD", value).encode( "ascii", "ignore").decode("ascii") value = SLUGIFY_STRIP_RE.sub("", value).strip().lower() return SLUGIFY_HYPHENATE_RE.sub("-", value) keystone-2014.1/keystone/openstack/common/context.py0000664000175400017540000000701512323716267023772 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # 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. """ Simple class that stores security context information in the web request. Projects should subclass this class if they wish to enhance the request context or provide additional information in their specific WSGI pipeline. """ import itertools import uuid def generate_request_id(): return 'req-%s' % str(uuid.uuid4()) class RequestContext(object): """Helper class to represent useful information about a request context. Stores information about the security context under which the user accesses the system, as well as additional request information. """ user_idt_format = '{user} {tenant} {domain} {user_domain} {p_domain}' def __init__(self, auth_token=None, user=None, tenant=None, domain=None, user_domain=None, project_domain=None, is_admin=False, read_only=False, show_deleted=False, request_id=None, instance_uuid=None): self.auth_token = auth_token self.user = user self.tenant = tenant self.domain = domain self.user_domain = user_domain self.project_domain = project_domain self.is_admin = is_admin self.read_only = read_only self.show_deleted = show_deleted self.instance_uuid = instance_uuid if not request_id: request_id = generate_request_id() self.request_id = request_id def to_dict(self): user_idt = ( self.user_idt_format.format(user=self.user or '-', tenant=self.tenant or '-', domain=self.domain or '-', user_domain=self.user_domain or '-', p_domain=self.project_domain or '-')) return {'user': self.user, 'tenant': self.tenant, 'domain': self.domain, 'user_domain': self.user_domain, 'project_domain': self.project_domain, 'is_admin': self.is_admin, 'read_only': self.read_only, 'show_deleted': self.show_deleted, 'auth_token': self.auth_token, 'request_id': self.request_id, 'instance_uuid': self.instance_uuid, 'user_identity': user_idt} def get_admin_context(show_deleted=False): context = RequestContext(None, tenant=None, is_admin=True, show_deleted=show_deleted) return context def get_context_from_function_and_args(function, args, kwargs): """Find an arg of type RequestContext and return it. This is useful in a couple of decorators where we don't know much about the function we're wrapping. """ for arg in itertools.chain(kwargs.values(), args): if isinstance(arg, RequestContext): return arg return None keystone-2014.1/keystone/openstack/common/lockutils.py0000664000175400017540000002334312323716267024321 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import contextlib import errno import functools import os import shutil import subprocess import sys import tempfile import threading import time import weakref from oslo.config import cfg from keystone.openstack.common import fileutils from keystone.openstack.common.gettextutils import _ # noqa from keystone.openstack.common import local from keystone.openstack.common import log as logging LOG = logging.getLogger(__name__) util_opts = [ cfg.BoolOpt('disable_process_locking', default=False, help='Whether to disable inter-process locks'), cfg.StrOpt('lock_path', default=os.environ.get("KEYSTONE_LOCK_PATH"), help=('Directory to use for lock files.')) ] CONF = cfg.CONF CONF.register_opts(util_opts) def set_defaults(lock_path): cfg.set_defaults(util_opts, lock_path=lock_path) class _InterProcessLock(object): """Lock implementation which allows multiple locks, working around issues like bugs.debian.org/cgi-bin/bugreport.cgi?bug=632857 and does not require any cleanup. Since the lock is always held on a file descriptor rather than outside of the process, the lock gets dropped automatically if the process crashes, even if __exit__ is not executed. There are no guarantees regarding usage by multiple green threads in a single process here. This lock works only between processes. Exclusive access between local threads should be achieved using the semaphores in the @synchronized decorator. Note these locks are released when the descriptor is closed, so it's not safe to close the file descriptor while another green thread holds the lock. Just opening and closing the lock file can break synchronisation, so lock files must be accessed only using this abstraction. """ def __init__(self, name): self.lockfile = None self.fname = name def __enter__(self): self.lockfile = open(self.fname, 'w') while True: try: # Using non-blocking locks since green threads are not # patched to deal with blocking locking calls. # Also upon reading the MSDN docs for locking(), it seems # to have a laughable 10 attempts "blocking" mechanism. self.trylock() return self except IOError as e: if e.errno in (errno.EACCES, errno.EAGAIN): # external locks synchronise things like iptables # updates - give it some time to prevent busy spinning time.sleep(0.01) else: raise def __exit__(self, exc_type, exc_val, exc_tb): try: self.unlock() self.lockfile.close() except IOError: LOG.exception(_("Could not release the acquired lock `%s`"), self.fname) def trylock(self): raise NotImplementedError() def unlock(self): raise NotImplementedError() class _WindowsLock(_InterProcessLock): def trylock(self): msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1) def unlock(self): msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1) class _PosixLock(_InterProcessLock): def trylock(self): fcntl.lockf(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) def unlock(self): fcntl.lockf(self.lockfile, fcntl.LOCK_UN) if os.name == 'nt': import msvcrt InterProcessLock = _WindowsLock else: import fcntl InterProcessLock = _PosixLock _semaphores = weakref.WeakValueDictionary() _semaphores_lock = threading.Lock() @contextlib.contextmanager def lock(name, lock_file_prefix=None, external=False, lock_path=None): """Context based lock This function yields a `threading.Semaphore` instance (if we don't use eventlet.monkey_patch(), else `semaphore.Semaphore`) unless external is True, in which case, it'll yield an InterProcessLock instance. :param lock_file_prefix: The lock_file_prefix argument is used to provide lock files on disk with a meaningful prefix. :param external: The external keyword argument denotes whether this lock should work across multiple processes. This means that if two different workers both run a a method decorated with @synchronized('mylock', external=True), only one of them will execute at a time. :param lock_path: The lock_path keyword argument is used to specify a special location for external lock files to live. If nothing is set, then CONF.lock_path is used as a default. """ with _semaphores_lock: try: sem = _semaphores[name] except KeyError: sem = threading.Semaphore() _semaphores[name] = sem with sem: LOG.debug(_('Got semaphore "%(lock)s"'), {'lock': name}) # NOTE(mikal): I know this looks odd if not hasattr(local.strong_store, 'locks_held'): local.strong_store.locks_held = [] local.strong_store.locks_held.append(name) try: if external and not CONF.disable_process_locking: LOG.debug(_('Attempting to grab file lock "%(lock)s"'), {'lock': name}) # We need a copy of lock_path because it is non-local local_lock_path = lock_path or CONF.lock_path if not local_lock_path: raise cfg.RequiredOptError('lock_path') if not os.path.exists(local_lock_path): fileutils.ensure_tree(local_lock_path) LOG.info(_('Created lock path: %s'), local_lock_path) def add_prefix(name, prefix): if not prefix: return name sep = '' if prefix.endswith('-') else '-' return '%s%s%s' % (prefix, sep, name) # NOTE(mikal): the lock name cannot contain directory # separators lock_file_name = add_prefix(name.replace(os.sep, '_'), lock_file_prefix) lock_file_path = os.path.join(local_lock_path, lock_file_name) try: lock = InterProcessLock(lock_file_path) with lock as lock: LOG.debug(_('Got file lock "%(lock)s" at %(path)s'), {'lock': name, 'path': lock_file_path}) yield lock finally: LOG.debug(_('Released file lock "%(lock)s" at %(path)s'), {'lock': name, 'path': lock_file_path}) else: yield sem finally: local.strong_store.locks_held.remove(name) def synchronized(name, lock_file_prefix=None, external=False, lock_path=None): """Synchronization decorator. Decorating a method like so:: @synchronized('mylock') def foo(self, *args): ... ensures that only one thread will execute the foo method at a time. Different methods can share the same lock:: @synchronized('mylock') def foo(self, *args): ... @synchronized('mylock') def bar(self, *args): ... This way only one of either foo or bar can be executing at a time. """ def wrap(f): @functools.wraps(f) def inner(*args, **kwargs): try: with lock(name, lock_file_prefix, external, lock_path): LOG.debug(_('Got semaphore / lock "%(function)s"'), {'function': f.__name__}) return f(*args, **kwargs) finally: LOG.debug(_('Semaphore / lock released "%(function)s"'), {'function': f.__name__}) return inner return wrap def synchronized_with_prefix(lock_file_prefix): """Partial object generator for the synchronization decorator. Redefine @synchronized in each project like so:: (in nova/utils.py) from nova.openstack.common import lockutils synchronized = lockutils.synchronized_with_prefix('nova-') (in nova/foo.py) from nova import utils @utils.synchronized('mylock') def bar(self, *args): ... The lock_file_prefix argument is used to provide lock files on disk with a meaningful prefix. """ return functools.partial(synchronized, lock_file_prefix=lock_file_prefix) def main(argv): """Create a dir for locks and pass it to command from arguments If you run this: python -m openstack.common.lockutils python setup.py testr a temporary directory will be created for all your locks and passed to all your tests in an environment variable. The temporary dir will be deleted afterwards and the return value will be preserved. """ lock_dir = tempfile.mkdtemp() os.environ["KEYSTONE_LOCK_PATH"] = lock_dir try: ret_val = subprocess.call(argv[1:]) finally: shutil.rmtree(lock_dir, ignore_errors=True) return ret_val if __name__ == '__main__': sys.exit(main(sys.argv)) keystone-2014.1/keystone/openstack/common/loopingcall.py0000664000175400017540000001103212323716267024603 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 Justin Santa Barbara # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sys from eventlet import event from eventlet import greenthread from keystone.openstack.common.gettextutils import _ # noqa from keystone.openstack.common import log as logging from keystone.openstack.common import timeutils LOG = logging.getLogger(__name__) class LoopingCallDone(Exception): """Exception to break out and stop a LoopingCall. The poll-function passed to LoopingCall can raise this exception to break out of the loop normally. This is somewhat analogous to StopIteration. An optional return-value can be included as the argument to the exception; this return-value will be returned by LoopingCall.wait() """ def __init__(self, retvalue=True): """:param retvalue: Value that LoopingCall.wait() should return.""" self.retvalue = retvalue class LoopingCallBase(object): def __init__(self, f=None, *args, **kw): self.args = args self.kw = kw self.f = f self._running = False self.done = None def stop(self): self._running = False def wait(self): return self.done.wait() class FixedIntervalLoopingCall(LoopingCallBase): """A fixed interval looping call.""" def start(self, interval, initial_delay=None): self._running = True done = event.Event() def _inner(): if initial_delay: greenthread.sleep(initial_delay) try: while self._running: start = timeutils.utcnow() self.f(*self.args, **self.kw) end = timeutils.utcnow() if not self._running: break delay = interval - timeutils.delta_seconds(start, end) if delay <= 0: LOG.warn(_('task run outlasted interval by %s sec') % -delay) greenthread.sleep(delay if delay > 0 else 0) except LoopingCallDone as e: self.stop() done.send(e.retvalue) except Exception: LOG.exception(_('in fixed duration looping call')) done.send_exception(*sys.exc_info()) return else: done.send(True) self.done = done greenthread.spawn_n(_inner) return self.done # TODO(mikal): this class name is deprecated in Havana and should be removed # in the I release LoopingCall = FixedIntervalLoopingCall class DynamicLoopingCall(LoopingCallBase): """A looping call which sleeps until the next known event. The function called should return how long to sleep for before being called again. """ def start(self, initial_delay=None, periodic_interval_max=None): self._running = True done = event.Event() def _inner(): if initial_delay: greenthread.sleep(initial_delay) try: while self._running: idle = self.f(*self.args, **self.kw) if not self._running: break if periodic_interval_max is not None: idle = min(idle, periodic_interval_max) LOG.debug(_('Dynamic looping call sleeping for %.02f ' 'seconds'), idle) greenthread.sleep(idle) except LoopingCallDone as e: self.stop() done.send(e.retvalue) except Exception: LOG.exception(_('in dynamic looping call')) done.send_exception(*sys.exc_info()) return else: done.send(True) self.done = done greenthread.spawn(_inner) return self.done keystone-2014.1/keystone/openstack/common/README0000664000175400017540000000072312323716267022613 0ustar jenkinsjenkins00000000000000openstack-common ---------------- A number of modules from openstack-common are imported into this project. These modules are "incubating" in openstack-common and are kept in sync with the help of openstack-common's update.py script. See: https://wiki.openstack.org/wiki/Oslo#Syncing_Code_from_Incubator The copy of the code should never be directly modified here. Please always update openstack-common first and then run the script to copy the changes across. keystone-2014.1/keystone/openstack/common/config/0000775000175400017540000000000012323716511023166 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/config/generator.py0000664000175400017540000002336012323716267025542 0ustar jenkinsjenkins00000000000000# Copyright 2012 SINA Corporation # All Rights Reserved. # # 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. # """Extracts OpenStack config option info from module(s).""" from __future__ import print_function import argparse import imp import os import re import socket import sys import textwrap from oslo.config import cfg import six import stevedore.named from keystone.openstack.common import gettextutils from keystone.openstack.common import importutils gettextutils.install('keystone') STROPT = "StrOpt" BOOLOPT = "BoolOpt" INTOPT = "IntOpt" FLOATOPT = "FloatOpt" LISTOPT = "ListOpt" MULTISTROPT = "MultiStrOpt" OPT_TYPES = { STROPT: 'string value', BOOLOPT: 'boolean value', INTOPT: 'integer value', FLOATOPT: 'floating point value', LISTOPT: 'list value', MULTISTROPT: 'multi valued', } OPTION_REGEX = re.compile(r"(%s)" % "|".join([STROPT, BOOLOPT, INTOPT, FLOATOPT, LISTOPT, MULTISTROPT])) PY_EXT = ".py" BASEDIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../")) WORDWRAP_WIDTH = 60 def generate(argv): parser = argparse.ArgumentParser( description='generate sample configuration file', ) parser.add_argument('-m', dest='modules', action='append') parser.add_argument('-l', dest='libraries', action='append') parser.add_argument('srcfiles', nargs='*') parsed_args = parser.parse_args(argv) mods_by_pkg = dict() for filepath in parsed_args.srcfiles: pkg_name = filepath.split(os.sep)[1] mod_str = '.'.join(['.'.join(filepath.split(os.sep)[:-1]), os.path.basename(filepath).split('.')[0]]) mods_by_pkg.setdefault(pkg_name, list()).append(mod_str) # NOTE(lzyeval): place top level modules before packages pkg_names = sorted(pkg for pkg in mods_by_pkg if pkg.endswith(PY_EXT)) ext_names = sorted(pkg for pkg in mods_by_pkg if pkg not in pkg_names) pkg_names.extend(ext_names) # opts_by_group is a mapping of group name to an options list # The options list is a list of (module, options) tuples opts_by_group = {'DEFAULT': []} if parsed_args.modules: for module_name in parsed_args.modules: module = _import_module(module_name) if module: for group, opts in _list_opts(module): opts_by_group.setdefault(group, []).append((module_name, opts)) # Look for entry points defined in libraries (or applications) for # option discovery, and include their return values in the output. # # Each entry point should be a function returning an iterable # of pairs with the group name (or None for the default group) # and the list of Opt instances for that group. if parsed_args.libraries: loader = stevedore.named.NamedExtensionManager( 'oslo.config.opts', names=list(set(parsed_args.libraries)), invoke_on_load=False, ) for ext in loader: for group, opts in ext.plugin(): opt_list = opts_by_group.setdefault(group or 'DEFAULT', []) opt_list.append((ext.name, opts)) for pkg_name in pkg_names: mods = mods_by_pkg.get(pkg_name) mods.sort() for mod_str in mods: if mod_str.endswith('.__init__'): mod_str = mod_str[:mod_str.rfind(".")] mod_obj = _import_module(mod_str) if not mod_obj: raise RuntimeError("Unable to import module %s" % mod_str) for group, opts in _list_opts(mod_obj): opts_by_group.setdefault(group, []).append((mod_str, opts)) print_group_opts('DEFAULT', opts_by_group.pop('DEFAULT', [])) for group in sorted(opts_by_group.keys()): print_group_opts(group, opts_by_group[group]) def _import_module(mod_str): try: if mod_str.startswith('bin.'): imp.load_source(mod_str[4:], os.path.join('bin', mod_str[4:])) return sys.modules[mod_str[4:]] else: return importutils.import_module(mod_str) except Exception as e: sys.stderr.write("Error importing module %s: %s\n" % (mod_str, str(e))) return None def _is_in_group(opt, group): "Check if opt is in group." for value in group._opts.values(): # NOTE(llu): Temporary workaround for bug #1262148, wait until # newly released oslo.config support '==' operator. if not(value['opt'] != opt): return True return False def _guess_groups(opt, mod_obj): # is it in the DEFAULT group? if _is_in_group(opt, cfg.CONF): return 'DEFAULT' # what other groups is it in? for value in cfg.CONF.values(): if isinstance(value, cfg.CONF.GroupAttr): if _is_in_group(opt, value._group): return value._group.name raise RuntimeError( "Unable to find group for option %s, " "maybe it's defined twice in the same group?" % opt.name ) def _list_opts(obj): def is_opt(o): return (isinstance(o, cfg.Opt) and not isinstance(o, cfg.SubCommandOpt)) opts = list() for attr_str in dir(obj): attr_obj = getattr(obj, attr_str) if is_opt(attr_obj): opts.append(attr_obj) elif (isinstance(attr_obj, list) and all(map(lambda x: is_opt(x), attr_obj))): opts.extend(attr_obj) ret = {} for opt in opts: ret.setdefault(_guess_groups(opt, obj), []).append(opt) return ret.items() def print_group_opts(group, opts_by_module): print("[%s]" % group) print('') for mod, opts in opts_by_module: print('#') print('# Options defined in %s' % mod) print('#') print('') for opt in opts: _print_opt(opt) print('') def _get_my_ip(): try: csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) csock.connect(('8.8.8.8', 80)) (addr, port) = csock.getsockname() csock.close() return addr except socket.error: return None def _sanitize_default(name, value): """Set up a reasonably sensible default for pybasedir, my_ip and host.""" if value.startswith(sys.prefix): # NOTE(jd) Don't use os.path.join, because it is likely to think the # second part is an absolute pathname and therefore drop the first # part. value = os.path.normpath("/usr/" + value[len(sys.prefix):]) elif value.startswith(BASEDIR): return value.replace(BASEDIR, '/usr/lib/python/site-packages') elif BASEDIR in value: return value.replace(BASEDIR, '') elif value == _get_my_ip(): return '10.0.0.1' elif value == socket.gethostname() and 'host' in name: return 'keystone' elif value.strip() != value: return '"%s"' % value return value def _print_opt(opt): opt_name, opt_default, opt_help = opt.dest, opt.default, opt.help if not opt_help: sys.stderr.write('WARNING: "%s" is missing help string.\n' % opt_name) opt_help = "" opt_type = None try: opt_type = OPTION_REGEX.search(str(type(opt))).group(0) except (ValueError, AttributeError) as err: sys.stderr.write("%s\n" % str(err)) sys.exit(1) opt_help += ' (' + OPT_TYPES[opt_type] + ')' print('#', "\n# ".join(textwrap.wrap(opt_help, WORDWRAP_WIDTH))) if opt.deprecated_opts: for deprecated_opt in opt.deprecated_opts: if deprecated_opt.name: deprecated_group = (deprecated_opt.group if deprecated_opt.group else "DEFAULT") print('# Deprecated group/name - [%s]/%s' % (deprecated_group, deprecated_opt.name)) try: if opt_default is None: print('#%s=' % opt_name) elif opt_type == STROPT: assert(isinstance(opt_default, six.string_types)) print('#%s=%s' % (opt_name, _sanitize_default(opt_name, opt_default))) elif opt_type == BOOLOPT: assert(isinstance(opt_default, bool)) print('#%s=%s' % (opt_name, str(opt_default).lower())) elif opt_type == INTOPT: assert(isinstance(opt_default, int) and not isinstance(opt_default, bool)) print('#%s=%s' % (opt_name, opt_default)) elif opt_type == FLOATOPT: assert(isinstance(opt_default, float)) print('#%s=%s' % (opt_name, opt_default)) elif opt_type == LISTOPT: assert(isinstance(opt_default, list)) print('#%s=%s' % (opt_name, ','.join(opt_default))) elif opt_type == MULTISTROPT: assert(isinstance(opt_default, list)) if not opt_default: opt_default = [''] for default in opt_default: print('#%s=%s' % (opt_name, default)) print('') except Exception: sys.stderr.write('Error in option "%s"\n' % opt_name) sys.exit(1) def main(): generate(sys.argv[1:]) if __name__ == '__main__': main() keystone-2014.1/keystone/openstack/common/config/__init__.py0000664000175400017540000000000012323716267025275 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/py3kcompat/0000775000175400017540000000000012323716511024013 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/py3kcompat/urlutils.py0000664000175400017540000000332012323716267026256 0ustar jenkinsjenkins00000000000000# # Copyright 2013 Canonical Ltd. # All Rights Reserved. # # 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. # """ Python2/Python3 compatibility layer for OpenStack """ import six if six.PY3: # python3 import urllib.error import urllib.parse import urllib.request urlencode = urllib.parse.urlencode urljoin = urllib.parse.urljoin quote = urllib.parse.quote parse_qsl = urllib.parse.parse_qsl unquote = urllib.parse.unquote urlparse = urllib.parse.urlparse urlsplit = urllib.parse.urlsplit urlunsplit = urllib.parse.urlunsplit SplitResult = urllib.parse.SplitResult urlopen = urllib.request.urlopen URLError = urllib.error.URLError pathname2url = urllib.request.pathname2url else: # python2 import urllib import urllib2 import urlparse urlencode = urllib.urlencode quote = urllib.quote unquote = urllib.unquote parse = urlparse parse_qsl = parse.parse_qsl urljoin = parse.urljoin urlparse = parse.urlparse urlsplit = parse.urlsplit urlunsplit = parse.urlunsplit SplitResult = parse.SplitResult urlopen = urllib2.urlopen URLError = urllib2.URLError pathname2url = urllib.pathname2url keystone-2014.1/keystone/openstack/common/py3kcompat/__init__.py0000664000175400017540000000117112323716267026134 0ustar jenkinsjenkins00000000000000# # Copyright 2013 Canonical Ltd. # All Rights Reserved. # # 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. # keystone-2014.1/keystone/openstack/common/timeutils.py0000664000175400017540000001406412323716267024327 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # 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. """ Time related utilities and helper functions. """ import calendar import datetime import time import iso8601 import six # ISO 8601 extended time format with microseconds _ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f' _ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S' PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND def isotime(at=None, subsecond=False): """Stringify time in ISO 8601 format.""" if not at: at = utcnow() st = at.strftime(_ISO8601_TIME_FORMAT if not subsecond else _ISO8601_TIME_FORMAT_SUBSECOND) tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' st += ('Z' if tz == 'UTC' else tz) return st def parse_isotime(timestr): """Parse time from ISO 8601 format.""" try: return iso8601.parse_date(timestr) except iso8601.ParseError as e: raise ValueError(six.text_type(e)) except TypeError as e: raise ValueError(six.text_type(e)) def strtime(at=None, fmt=PERFECT_TIME_FORMAT): """Returns formatted utcnow.""" if not at: at = utcnow() return at.strftime(fmt) def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): """Turn a formatted time back into a datetime.""" return datetime.datetime.strptime(timestr, fmt) def normalize_time(timestamp): """Normalize time in arbitrary timezone to UTC naive object.""" offset = timestamp.utcoffset() if offset is None: return timestamp return timestamp.replace(tzinfo=None) - offset def is_older_than(before, seconds): """Return True if before is older than seconds.""" if isinstance(before, six.string_types): before = parse_strtime(before).replace(tzinfo=None) return utcnow() - before > datetime.timedelta(seconds=seconds) def is_newer_than(after, seconds): """Return True if after is newer than seconds.""" if isinstance(after, six.string_types): after = parse_strtime(after).replace(tzinfo=None) return after - utcnow() > datetime.timedelta(seconds=seconds) def utcnow_ts(): """Timestamp version of our utcnow function.""" if utcnow.override_time is None: # NOTE(kgriffs): This is several times faster # than going through calendar.timegm(...) return int(time.time()) return calendar.timegm(utcnow().timetuple()) def utcnow(): """Overridable version of utils.utcnow.""" if utcnow.override_time: try: return utcnow.override_time.pop(0) except AttributeError: return utcnow.override_time return datetime.datetime.utcnow() def iso8601_from_timestamp(timestamp): """Returns a iso8601 formated date from timestamp.""" return isotime(datetime.datetime.utcfromtimestamp(timestamp)) utcnow.override_time = None def set_time_override(override_time=None): """Overrides utils.utcnow. Make it return a constant time or a list thereof, one at a time. :param override_time: datetime instance or list thereof. If not given, defaults to the current UTC time. """ utcnow.override_time = override_time or datetime.datetime.utcnow() def advance_time_delta(timedelta): """Advance overridden time using a datetime.timedelta.""" assert(not utcnow.override_time is None) try: for dt in utcnow.override_time: dt += timedelta except TypeError: utcnow.override_time += timedelta def advance_time_seconds(seconds): """Advance overridden time by seconds.""" advance_time_delta(datetime.timedelta(0, seconds)) def clear_time_override(): """Remove the overridden time.""" utcnow.override_time = None def marshall_now(now=None): """Make an rpc-safe datetime with microseconds. Note: tzinfo is stripped, but not required for relative times. """ if not now: now = utcnow() return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, minute=now.minute, second=now.second, microsecond=now.microsecond) def unmarshall_time(tyme): """Unmarshall a datetime dict.""" return datetime.datetime(day=tyme['day'], month=tyme['month'], year=tyme['year'], hour=tyme['hour'], minute=tyme['minute'], second=tyme['second'], microsecond=tyme['microsecond']) def delta_seconds(before, after): """Return the difference between two timing objects. Compute the difference in seconds between two date, time, or datetime objects (as a float, to microsecond resolution). """ delta = after - before return total_seconds(delta) def total_seconds(delta): """Return the total seconds of datetime.timedelta object. Compute total seconds of datetime.timedelta, datetime.timedelta doesn't have method total_seconds in Python2.6, calculate it manually. """ try: return delta.total_seconds() except AttributeError: return ((delta.days * 24 * 3600) + delta.seconds + float(delta.microseconds) / (10 ** 6)) def is_soon(dt, window): """Determines if time is going to happen in the next window seconds. :params dt: the time :params window: minimum seconds to remain to consider the time not soon :return: True if expiration is within the given duration """ soon = (utcnow() + datetime.timedelta(seconds=window)) return normalize_time(dt) <= soon keystone-2014.1/keystone/openstack/common/policy.py0000664000175400017540000006314212323716267023610 0ustar jenkinsjenkins00000000000000# Copyright (c) 2012 OpenStack Foundation. # All Rights Reserved. # # 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. """ Common Policy Engine Implementation Policies can be expressed in one of two forms: A list of lists, or a string written in the new policy language. In the list-of-lists representation, each check inside the innermost list is combined as with an "and" conjunction--for that check to pass, all the specified checks must pass. These innermost lists are then combined as with an "or" conjunction. This is the original way of expressing policies, but there now exists a new way: the policy language. In the policy language, each check is specified the same way as in the list-of-lists representation: a simple "a:b" pair that is matched to the correct code to perform that check. However, conjunction operators are available, allowing for more expressiveness in crafting policies. As an example, take the following rule, expressed in the list-of-lists representation:: [["role:admin"], ["project_id:%(project_id)s", "role:projectadmin"]] In the policy language, this becomes:: role:admin or (project_id:%(project_id)s and role:projectadmin) The policy language also has the "not" operator, allowing a richer policy rule:: project_id:%(project_id)s and not role:dunce Finally, two special policy checks should be mentioned; the policy check "@" will always accept an access, and the policy check "!" will always reject an access. (Note that if a rule is either the empty list ("[]") or the empty string, this is equivalent to the "@" policy check.) Of these, the "!" policy check is probably the most useful, as it allows particular rules to be explicitly disabled. """ import abc import ast import re from oslo.config import cfg import six import six.moves.urllib.parse as urlparse import six.moves.urllib.request as urlrequest from keystone.openstack.common import fileutils from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils from keystone.openstack.common import log as logging policy_opts = [ cfg.StrOpt('policy_file', default='policy.json', help=_('JSON file containing policy')), cfg.StrOpt('policy_default_rule', default='default', help=_('Rule enforced when requested rule is not found')), ] CONF = cfg.CONF CONF.register_opts(policy_opts) LOG = logging.getLogger(__name__) _checks = {} class PolicyNotAuthorized(Exception): def __init__(self, rule): msg = _("Policy doesn't allow %s to be performed.") % rule super(PolicyNotAuthorized, self).__init__(msg) class Rules(dict): """A store for rules. Handles the default_rule setting directly.""" @classmethod def load_json(cls, data, default_rule=None): """Allow loading of JSON rule data.""" # Suck in the JSON data and parse the rules rules = dict((k, parse_rule(v)) for k, v in jsonutils.loads(data).items()) return cls(rules, default_rule) def __init__(self, rules=None, default_rule=None): """Initialize the Rules store.""" super(Rules, self).__init__(rules or {}) self.default_rule = default_rule def __missing__(self, key): """Implements the default rule handling.""" if isinstance(self.default_rule, dict): raise KeyError(key) # If the default rule isn't actually defined, do something # reasonably intelligent if not self.default_rule: raise KeyError(key) if isinstance(self.default_rule, BaseCheck): return self.default_rule # We need to check this or we can get infinite recursion if self.default_rule not in self: raise KeyError(key) elif isinstance(self.default_rule, six.string_types): return self[self.default_rule] def __str__(self): """Dumps a string representation of the rules.""" # Start by building the canonical strings for the rules out_rules = {} for key, value in self.items(): # Use empty string for singleton TrueCheck instances if isinstance(value, TrueCheck): out_rules[key] = '' else: out_rules[key] = str(value) # Dump a pretty-printed JSON representation return jsonutils.dumps(out_rules, indent=4) class Enforcer(object): """Responsible for loading and enforcing rules. :param policy_file: Custom policy file to use, if none is specified, `CONF.policy_file` will be used. :param rules: Default dictionary / Rules to use. It will be considered just in the first instantiation. If `load_rules(True)`, `clear()` or `set_rules(True)` is called this will be overwritten. :param default_rule: Default rule to use, CONF.default_rule will be used if none is specified. """ def __init__(self, policy_file=None, rules=None, default_rule=None): self.rules = Rules(rules, default_rule) self.default_rule = default_rule or CONF.policy_default_rule self.policy_path = None self.policy_file = policy_file or CONF.policy_file def set_rules(self, rules, overwrite=True): """Create a new Rules object based on the provided dict of rules. :param rules: New rules to use. It should be an instance of dict. :param overwrite: Whether to overwrite current rules or update them with the new rules. """ if not isinstance(rules, dict): raise TypeError(_("Rules must be an instance of dict or Rules, " "got %s instead") % type(rules)) if overwrite: self.rules = Rules(rules, self.default_rule) else: self.rules.update(rules) def clear(self): """Clears Enforcer rules, policy's cache and policy's path.""" self.set_rules({}) self.default_rule = None self.policy_path = None def load_rules(self, force_reload=False): """Loads policy_path's rules. Policy file is cached and will be reloaded if modified. :param force_reload: Whether to overwrite current rules. """ if not self.policy_path: self.policy_path = self._get_policy_path() reloaded, data = fileutils.read_cached_file(self.policy_path, force_reload=force_reload) if reloaded or not self.rules: rules = Rules.load_json(data, self.default_rule) self.set_rules(rules) LOG.debug(_("Rules successfully reloaded")) def _get_policy_path(self): """Locate the policy json data file. :param policy_file: Custom policy file to locate. :returns: The policy path :raises: ConfigFilesNotFoundError if the file couldn't be located. """ policy_file = CONF.find_file(self.policy_file) if policy_file: return policy_file raise cfg.ConfigFilesNotFoundError((self.policy_file,)) def enforce(self, rule, target, creds, do_raise=False, exc=None, *args, **kwargs): """Checks authorization of a rule against the target and credentials. :param rule: A string or BaseCheck instance specifying the rule to evaluate. :param target: As much information about the object being operated on as possible, as a dictionary. :param creds: As much information about the user performing the action as possible, as a dictionary. :param do_raise: Whether to raise an exception or not if check fails. :param exc: Class of the exception to raise if the check fails. Any remaining arguments passed to check() (both positional and keyword arguments) will be passed to the exception class. If not specified, PolicyNotAuthorized will be used. :return: Returns False if the policy does not allow the action and exc is not provided; otherwise, returns a value that evaluates to True. Note: for rules using the "case" expression, this True value will be the specified string from the expression. """ # NOTE(flaper87): Not logging target or creds to avoid # potential security issues. LOG.debug(_("Rule %s will be now enforced") % rule) self.load_rules() # Allow the rule to be a Check tree if isinstance(rule, BaseCheck): result = rule(target, creds, self) elif not self.rules: # No rules to reference means we're going to fail closed result = False else: try: # Evaluate the rule result = self.rules[rule](target, creds, self) except KeyError: LOG.debug(_("Rule [%s] doesn't exist") % rule) # If the rule doesn't exist, fail closed result = False # If it is False, raise the exception if requested if do_raise and not result: if exc: raise exc(*args, **kwargs) raise PolicyNotAuthorized(rule) return result @six.add_metaclass(abc.ABCMeta) class BaseCheck(object): """Abstract base class for Check classes.""" @abc.abstractmethod def __str__(self): """String representation of the Check tree rooted at this node.""" pass @abc.abstractmethod def __call__(self, target, cred, enforcer): """Triggers if instance of the class is called. Performs the check. Returns False to reject the access or a true value (not necessary True) to accept the access. """ pass class FalseCheck(BaseCheck): """A policy check that always returns False (disallow).""" def __str__(self): """Return a string representation of this check.""" return "!" def __call__(self, target, cred, enforcer): """Check the policy.""" return False class TrueCheck(BaseCheck): """A policy check that always returns True (allow).""" def __str__(self): """Return a string representation of this check.""" return "@" def __call__(self, target, cred, enforcer): """Check the policy.""" return True class Check(BaseCheck): """A base class to allow for user-defined policy checks.""" def __init__(self, kind, match): """Initiates Check instance. :param kind: The kind of the check, i.e., the field before the ':'. :param match: The match of the check, i.e., the field after the ':'. """ self.kind = kind self.match = match def __str__(self): """Return a string representation of this check.""" return "%s:%s" % (self.kind, self.match) class NotCheck(BaseCheck): """Implements the "not" logical operator. A policy check that inverts the result of another policy check. """ def __init__(self, rule): """Initialize the 'not' check. :param rule: The rule to negate. Must be a Check. """ self.rule = rule def __str__(self): """Return a string representation of this check.""" return "not %s" % self.rule def __call__(self, target, cred, enforcer): """Check the policy. Returns the logical inverse of the wrapped check. """ return not self.rule(target, cred, enforcer) class AndCheck(BaseCheck): """Implements the "and" logical operator. A policy check that requires that a list of other checks all return True. """ def __init__(self, rules): """Initialize the 'and' check. :param rules: A list of rules that will be tested. """ self.rules = rules def __str__(self): """Return a string representation of this check.""" return "(%s)" % ' and '.join(str(r) for r in self.rules) def __call__(self, target, cred, enforcer): """Check the policy. Requires that all rules accept in order to return True. """ for rule in self.rules: if not rule(target, cred, enforcer): return False return True def add_check(self, rule): """Adds rule to be tested. Allows addition of another rule to the list of rules that will be tested. Returns the AndCheck object for convenience. """ self.rules.append(rule) return self class OrCheck(BaseCheck): """Implements the "or" operator. A policy check that requires that at least one of a list of other checks returns True. """ def __init__(self, rules): """Initialize the 'or' check. :param rules: A list of rules that will be tested. """ self.rules = rules def __str__(self): """Return a string representation of this check.""" return "(%s)" % ' or '.join(str(r) for r in self.rules) def __call__(self, target, cred, enforcer): """Check the policy. Requires that at least one rule accept in order to return True. """ for rule in self.rules: if rule(target, cred, enforcer): return True return False def add_check(self, rule): """Adds rule to be tested. Allows addition of another rule to the list of rules that will be tested. Returns the OrCheck object for convenience. """ self.rules.append(rule) return self def _parse_check(rule): """Parse a single base check rule into an appropriate Check object.""" # Handle the special checks if rule == '!': return FalseCheck() elif rule == '@': return TrueCheck() try: kind, match = rule.split(':', 1) except Exception: LOG.exception(_("Failed to understand rule %s") % rule) # If the rule is invalid, we'll fail closed return FalseCheck() # Find what implements the check if kind in _checks: return _checks[kind](kind, match) elif None in _checks: return _checks[None](kind, match) else: LOG.error(_("No handler for matches of kind %s") % kind) return FalseCheck() def _parse_list_rule(rule): """Translates the old list-of-lists syntax into a tree of Check objects. Provided for backwards compatibility. """ # Empty rule defaults to True if not rule: return TrueCheck() # Outer list is joined by "or"; inner list by "and" or_list = [] for inner_rule in rule: # Elide empty inner lists if not inner_rule: continue # Handle bare strings if isinstance(inner_rule, six.string_types): inner_rule = [inner_rule] # Parse the inner rules into Check objects and_list = [_parse_check(r) for r in inner_rule] # Append the appropriate check to the or_list if len(and_list) == 1: or_list.append(and_list[0]) else: or_list.append(AndCheck(and_list)) # If we have only one check, omit the "or" if not or_list: return FalseCheck() elif len(or_list) == 1: return or_list[0] return OrCheck(or_list) # Used for tokenizing the policy language _tokenize_re = re.compile(r'\s+') def _parse_tokenize(rule): """Tokenizer for the policy language. Most of the single-character tokens are specified in the _tokenize_re; however, parentheses need to be handled specially, because they can appear inside a check string. Thankfully, those parentheses that appear inside a check string can never occur at the very beginning or end ("%(variable)s" is the correct syntax). """ for tok in _tokenize_re.split(rule): # Skip empty tokens if not tok or tok.isspace(): continue # Handle leading parens on the token clean = tok.lstrip('(') for i in range(len(tok) - len(clean)): yield '(', '(' # If it was only parentheses, continue if not clean: continue else: tok = clean # Handle trailing parens on the token clean = tok.rstrip(')') trail = len(tok) - len(clean) # Yield the cleaned token lowered = clean.lower() if lowered in ('and', 'or', 'not'): # Special tokens yield lowered, clean elif clean: # Not a special token, but not composed solely of ')' if len(tok) >= 2 and ((tok[0], tok[-1]) in [('"', '"'), ("'", "'")]): # It's a quoted string yield 'string', tok[1:-1] else: yield 'check', _parse_check(clean) # Yield the trailing parens for i in range(trail): yield ')', ')' class ParseStateMeta(type): """Metaclass for the ParseState class. Facilitates identifying reduction methods. """ def __new__(mcs, name, bases, cls_dict): """Create the class. Injects the 'reducers' list, a list of tuples matching token sequences to the names of the corresponding reduction methods. """ reducers = [] for key, value in cls_dict.items(): if not hasattr(value, 'reducers'): continue for reduction in value.reducers: reducers.append((reduction, key)) cls_dict['reducers'] = reducers return super(ParseStateMeta, mcs).__new__(mcs, name, bases, cls_dict) def reducer(*tokens): """Decorator for reduction methods. Arguments are a sequence of tokens, in order, which should trigger running this reduction method. """ def decorator(func): # Make sure we have a list of reducer sequences if not hasattr(func, 'reducers'): func.reducers = [] # Add the tokens to the list of reducer sequences func.reducers.append(list(tokens)) return func return decorator @six.add_metaclass(ParseStateMeta) class ParseState(object): """Implement the core of parsing the policy language. Uses a greedy reduction algorithm to reduce a sequence of tokens into a single terminal, the value of which will be the root of the Check tree. Note: error reporting is rather lacking. The best we can get with this parser formulation is an overall "parse failed" error. Fortunately, the policy language is simple enough that this shouldn't be that big a problem. """ def __init__(self): """Initialize the ParseState.""" self.tokens = [] self.values = [] def reduce(self): """Perform a greedy reduction of the token stream. If a reducer method matches, it will be executed, then the reduce() method will be called recursively to search for any more possible reductions. """ for reduction, methname in self.reducers: if (len(self.tokens) >= len(reduction) and self.tokens[-len(reduction):] == reduction): # Get the reduction method meth = getattr(self, methname) # Reduce the token stream results = meth(*self.values[-len(reduction):]) # Update the tokens and values self.tokens[-len(reduction):] = [r[0] for r in results] self.values[-len(reduction):] = [r[1] for r in results] # Check for any more reductions return self.reduce() def shift(self, tok, value): """Adds one more token to the state. Calls reduce().""" self.tokens.append(tok) self.values.append(value) # Do a greedy reduce... self.reduce() @property def result(self): """Obtain the final result of the parse. Raises ValueError if the parse failed to reduce to a single result. """ if len(self.values) != 1: raise ValueError("Could not parse rule") return self.values[0] @reducer('(', 'check', ')') @reducer('(', 'and_expr', ')') @reducer('(', 'or_expr', ')') def _wrap_check(self, _p1, check, _p2): """Turn parenthesized expressions into a 'check' token.""" return [('check', check)] @reducer('check', 'and', 'check') def _make_and_expr(self, check1, _and, check2): """Create an 'and_expr'. Join two checks by the 'and' operator. """ return [('and_expr', AndCheck([check1, check2]))] @reducer('and_expr', 'and', 'check') def _extend_and_expr(self, and_expr, _and, check): """Extend an 'and_expr' by adding one more check.""" return [('and_expr', and_expr.add_check(check))] @reducer('check', 'or', 'check') def _make_or_expr(self, check1, _or, check2): """Create an 'or_expr'. Join two checks by the 'or' operator. """ return [('or_expr', OrCheck([check1, check2]))] @reducer('or_expr', 'or', 'check') def _extend_or_expr(self, or_expr, _or, check): """Extend an 'or_expr' by adding one more check.""" return [('or_expr', or_expr.add_check(check))] @reducer('not', 'check') def _make_not_expr(self, _not, check): """Invert the result of another check.""" return [('check', NotCheck(check))] def _parse_text_rule(rule): """Parses policy to the tree. Translates a policy written in the policy language into a tree of Check objects. """ # Empty rule means always accept if not rule: return TrueCheck() # Parse the token stream state = ParseState() for tok, value in _parse_tokenize(rule): state.shift(tok, value) try: return state.result except ValueError: # Couldn't parse the rule LOG.exception(_("Failed to understand rule %r") % rule) # Fail closed return FalseCheck() def parse_rule(rule): """Parses a policy rule into a tree of Check objects.""" # If the rule is a string, it's in the policy language if isinstance(rule, six.string_types): return _parse_text_rule(rule) return _parse_list_rule(rule) def register(name, func=None): """Register a function or Check class as a policy check. :param name: Gives the name of the check type, e.g., 'rule', 'role', etc. If name is None, a default check type will be registered. :param func: If given, provides the function or class to register. If not given, returns a function taking one argument to specify the function or class to register, allowing use as a decorator. """ # Perform the actual decoration by registering the function or # class. Returns the function or class for compliance with the # decorator interface. def decorator(func): _checks[name] = func return func # If the function or class is given, do the registration if func: return decorator(func) return decorator @register("rule") class RuleCheck(Check): def __call__(self, target, creds, enforcer): """Recursively checks credentials based on the defined rules.""" try: return enforcer.rules[self.match](target, creds, enforcer) except KeyError: # We don't have any matching rule; fail closed return False @register("role") class RoleCheck(Check): def __call__(self, target, creds, enforcer): """Check that there is a matching role in the cred dict.""" return self.match.lower() in [x.lower() for x in creds['roles']] @register('http') class HttpCheck(Check): def __call__(self, target, creds, enforcer): """Check http: rules by calling to a remote server. This example implementation simply verifies that the response is exactly 'True'. """ url = ('http:' + self.match) % target data = {'target': jsonutils.dumps(target), 'credentials': jsonutils.dumps(creds)} post_data = urlparse.urlencode(data) f = urlrequest.urlopen(url, post_data) return f.read() == "True" @register(None) class GenericCheck(Check): def __call__(self, target, creds, enforcer): """Check an individual match. Matches look like: tenant:%(tenant_id)s role:compute:admin True:%(user.enabled)s 'Member':%(role.name)s """ # TODO(termie): do dict inspection via dot syntax try: match = self.match % target except KeyError: # While doing GenericCheck if key not # present in Target return false return False try: # Try to interpret self.kind as a literal leftval = ast.literal_eval(self.kind) except ValueError: try: leftval = creds[self.kind] except KeyError: return False return match == six.text_type(leftval) keystone-2014.1/keystone/openstack/common/processutils.py0000664000175400017540000002230312323716267025042 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # 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. """ System-level utilities and helper functions. """ import logging as stdlib_logging import os import random import shlex import signal from eventlet.green import subprocess from eventlet import greenthread from keystone.openstack.common.gettextutils import _ # noqa from keystone.openstack.common import log as logging LOG = logging.getLogger(__name__) class InvalidArgumentError(Exception): def __init__(self, message=None): super(InvalidArgumentError, self).__init__(message) class UnknownArgumentError(Exception): def __init__(self, message=None): super(UnknownArgumentError, self).__init__(message) class ProcessExecutionError(Exception): def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None, description=None): self.exit_code = exit_code self.stderr = stderr self.stdout = stdout self.cmd = cmd self.description = description if description is None: description = "Unexpected error while running command." if exit_code is None: exit_code = '-' message = ("%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r" % (description, cmd, exit_code, stdout, stderr)) super(ProcessExecutionError, self).__init__(message) class NoRootWrapSpecified(Exception): def __init__(self, message=None): super(NoRootWrapSpecified, self).__init__(message) def _subprocess_setup(): # Python installs a SIGPIPE handler by default. This is usually not what # non-Python subprocesses expect. signal.signal(signal.SIGPIPE, signal.SIG_DFL) def execute(*cmd, **kwargs): """Helper method to shell out and execute a command through subprocess. Allows optional retry. :param cmd: Passed to subprocess.Popen. :type cmd: string :param process_input: Send to opened process. :type proces_input: string :param check_exit_code: Single bool, int, or list of allowed exit codes. Defaults to [0]. Raise :class:`ProcessExecutionError` unless program exits with one of these code. :type check_exit_code: boolean, int, or [int] :param delay_on_retry: True | False. Defaults to True. If set to True, wait a short amount of time before retrying. :type delay_on_retry: boolean :param attempts: How many times to retry cmd. :type attempts: int :param run_as_root: True | False. Defaults to False. If set to True, the command is prefixed by the command specified in the root_helper kwarg. :type run_as_root: boolean :param root_helper: command to prefix to commands called with run_as_root=True :type root_helper: string :param shell: whether or not there should be a shell used to execute this command. Defaults to false. :type shell: boolean :param loglevel: log level for execute commands. :type loglevel: int. (Should be stdlib_logging.DEBUG or stdlib_logging.INFO) :returns: (stdout, stderr) from process execution :raises: :class:`UnknownArgumentError` on receiving unknown arguments :raises: :class:`ProcessExecutionError` """ process_input = kwargs.pop('process_input', None) check_exit_code = kwargs.pop('check_exit_code', [0]) ignore_exit_code = False delay_on_retry = kwargs.pop('delay_on_retry', True) attempts = kwargs.pop('attempts', 1) run_as_root = kwargs.pop('run_as_root', False) root_helper = kwargs.pop('root_helper', '') shell = kwargs.pop('shell', False) loglevel = kwargs.pop('loglevel', stdlib_logging.DEBUG) if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code check_exit_code = [0] elif isinstance(check_exit_code, int): check_exit_code = [check_exit_code] if kwargs: raise UnknownArgumentError(_('Got unknown keyword args ' 'to utils.execute: %r') % kwargs) if run_as_root and hasattr(os, 'geteuid') and os.geteuid() != 0: if not root_helper: raise NoRootWrapSpecified( message=('Command requested root, but did not specify a root ' 'helper.')) cmd = shlex.split(root_helper) + list(cmd) cmd = map(str, cmd) while attempts > 0: attempts -= 1 try: LOG.log(loglevel, _('Running cmd (subprocess): %s'), ' '.join(cmd)) _PIPE = subprocess.PIPE # pylint: disable=E1101 if os.name == 'nt': preexec_fn = None close_fds = False else: preexec_fn = _subprocess_setup close_fds = True obj = subprocess.Popen(cmd, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE, close_fds=close_fds, preexec_fn=preexec_fn, shell=shell) result = None if process_input is not None: result = obj.communicate(process_input) else: result = obj.communicate() obj.stdin.close() # pylint: disable=E1101 _returncode = obj.returncode # pylint: disable=E1101 LOG.log(loglevel, _('Result was %s') % _returncode) if not ignore_exit_code and _returncode not in check_exit_code: (stdout, stderr) = result raise ProcessExecutionError(exit_code=_returncode, stdout=stdout, stderr=stderr, cmd=' '.join(cmd)) return result except ProcessExecutionError: if not attempts: raise else: LOG.log(loglevel, _('%r failed. Retrying.'), cmd) if delay_on_retry: greenthread.sleep(random.randint(20, 200) / 100.0) finally: # NOTE(termie): this appears to be necessary to let the subprocess # call clean something up in between calls, without # it two execute calls in a row hangs the second one greenthread.sleep(0) def trycmd(*args, **kwargs): """A wrapper around execute() to more easily handle warnings and errors. Returns an (out, err) tuple of strings containing the output of the command's stdout and stderr. If 'err' is not empty then the command can be considered to have failed. :discard_warnings True | False. Defaults to False. If set to True, then for succeeding commands, stderr is cleared """ discard_warnings = kwargs.pop('discard_warnings', False) try: out, err = execute(*args, **kwargs) failed = False except ProcessExecutionError as exn: out, err = '', str(exn) failed = True if not failed and discard_warnings and err: # Handle commands that output to stderr but otherwise succeed err = '' return out, err def ssh_execute(ssh, cmd, process_input=None, addl_env=None, check_exit_code=True): LOG.debug(_('Running cmd (SSH): %s'), cmd) if addl_env: raise InvalidArgumentError(_('Environment not supported over SSH')) if process_input: # This is (probably) fixable if we need it... raise InvalidArgumentError(_('process_input not supported over SSH')) stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) channel = stdout_stream.channel # NOTE(justinsb): This seems suspicious... # ...other SSH clients have buffering issues with this approach stdout = stdout_stream.read() stderr = stderr_stream.read() stdin_stream.close() exit_status = channel.recv_exit_status() # exit_status == -1 if no exit code was returned if exit_status != -1: LOG.debug(_('Result was %s') % exit_status) if check_exit_code and exit_status != 0: raise ProcessExecutionError(exit_code=exit_status, stdout=stdout, stderr=stderr, cmd=cmd) return (stdout, stderr) keystone-2014.1/keystone/openstack/common/jsonutils.py0000664000175400017540000001440112323716267024335 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 Justin Santa Barbara # All Rights Reserved. # # 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. ''' JSON related utilities. This module provides a few things: 1) A handy function for getting an object down to something that can be JSON serialized. See to_primitive(). 2) Wrappers around loads() and dumps(). The dumps() wrapper will automatically use to_primitive() for you if needed. 3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson is available. ''' import datetime import functools import inspect import itertools import json try: import xmlrpclib except ImportError: # NOTE(jd): xmlrpclib is not shipped with Python 3 xmlrpclib = None import six from keystone.openstack.common import gettextutils from keystone.openstack.common import importutils from keystone.openstack.common import timeutils netaddr = importutils.try_import("netaddr") _nasty_type_tests = [inspect.ismodule, inspect.isclass, inspect.ismethod, inspect.isfunction, inspect.isgeneratorfunction, inspect.isgenerator, inspect.istraceback, inspect.isframe, inspect.iscode, inspect.isbuiltin, inspect.isroutine, inspect.isabstract] _simple_types = (six.string_types + six.integer_types + (type(None), bool, float)) def to_primitive(value, convert_instances=False, convert_datetime=True, level=0, max_depth=3): """Convert a complex object into primitives. Handy for JSON serialization. We can optionally handle instances, but since this is a recursive function, we could have cyclical data structures. To handle cyclical data structures we could track the actual objects visited in a set, but not all objects are hashable. Instead we just track the depth of the object inspections and don't go too deep. Therefore, convert_instances=True is lossy ... be aware. """ # handle obvious types first - order of basic types determined by running # full tests on nova project, resulting in the following counts: # 572754 # 460353 # 379632 # 274610 # 199918 # 114200 # 51817 # 26164 # 6491 # 283 # 19 if isinstance(value, _simple_types): return value if isinstance(value, datetime.datetime): if convert_datetime: return timeutils.strtime(value) else: return value # value of itertools.count doesn't get caught by nasty_type_tests # and results in infinite loop when list(value) is called. if type(value) == itertools.count: return six.text_type(value) # FIXME(vish): Workaround for LP bug 852095. Without this workaround, # tests that raise an exception in a mocked method that # has a @wrap_exception with a notifier will fail. If # we up the dependency to 0.5.4 (when it is released) we # can remove this workaround. if getattr(value, '__module__', None) == 'mox': return 'mock' if level > max_depth: return '?' # The try block may not be necessary after the class check above, # but just in case ... try: recursive = functools.partial(to_primitive, convert_instances=convert_instances, convert_datetime=convert_datetime, level=level, max_depth=max_depth) if isinstance(value, dict): return dict((k, recursive(v)) for k, v in value.iteritems()) elif isinstance(value, (list, tuple)): return [recursive(lv) for lv in value] # It's not clear why xmlrpclib created their own DateTime type, but # for our purposes, make it a datetime type which is explicitly # handled if xmlrpclib and isinstance(value, xmlrpclib.DateTime): value = datetime.datetime(*tuple(value.timetuple())[:6]) if convert_datetime and isinstance(value, datetime.datetime): return timeutils.strtime(value) elif isinstance(value, gettextutils.Message): return value.data elif hasattr(value, 'iteritems'): return recursive(dict(value.iteritems()), level=level + 1) elif hasattr(value, '__iter__'): return recursive(list(value)) elif convert_instances and hasattr(value, '__dict__'): # Likely an instance of something. Watch for cycles. # Ignore class member vars. return recursive(value.__dict__, level=level + 1) elif netaddr and isinstance(value, netaddr.IPAddress): return six.text_type(value) else: if any(test(value) for test in _nasty_type_tests): return six.text_type(value) return value except TypeError: # Class objects are tricky since they may define something like # __iter__ defined but it isn't callable as list(). return six.text_type(value) def dumps(value, default=to_primitive, **kwargs): return json.dumps(value, default=default, **kwargs) def loads(s): return json.loads(s) def load(s): return json.load(s) try: import anyjson except ImportError: pass else: anyjson._modules.append((__name__, 'dumps', TypeError, 'loads', ValueError, 'load')) anyjson.force_implementation(__name__) keystone-2014.1/keystone/openstack/common/gettextutils.py0000664000175400017540000004456012323716267025061 0ustar jenkinsjenkins00000000000000# Copyright 2012 Red Hat, Inc. # Copyright 2013 IBM Corp. # All Rights Reserved. # # 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. """ gettext for openstack-common modules. Usual usage in an openstack.common module: from keystone.openstack.common.gettextutils import _ """ import copy import functools import gettext import locale from logging import handlers import os import re from babel import localedata import six _localedir = os.environ.get('keystone'.upper() + '_LOCALEDIR') _t = gettext.translation('keystone', localedir=_localedir, fallback=True) # We use separate translation catalogs for each log level, so set up a # mapping between the log level name and the translator. The domain # for the log level is project_name + "-log-" + log_level so messages # for each level end up in their own catalog. _t_log_levels = dict( (level, gettext.translation('keystone' + '-log-' + level, localedir=_localedir, fallback=True)) for level in ['info', 'warning', 'error', 'critical'] ) _AVAILABLE_LANGUAGES = {} USE_LAZY = False def enable_lazy(): """Convenience function for configuring _() to use lazy gettext Call this at the start of execution to enable the gettextutils._ function to use lazy gettext functionality. This is useful if your project is importing _ directly instead of using the gettextutils.install() way of importing the _ function. """ global USE_LAZY USE_LAZY = True def _(msg): if USE_LAZY: return Message(msg, domain='keystone') else: if six.PY3: return _t.gettext(msg) return _t.ugettext(msg) def _log_translation(msg, level): """Build a single translation of a log message """ if USE_LAZY: return Message(msg, domain='keystone' + '-log-' + level) else: translator = _t_log_levels[level] if six.PY3: return translator.gettext(msg) return translator.ugettext(msg) # Translators for log levels. # # The abbreviated names are meant to reflect the usual use of a short # name like '_'. The "L" is for "log" and the other letter comes from # the level. _LI = functools.partial(_log_translation, level='info') _LW = functools.partial(_log_translation, level='warning') _LE = functools.partial(_log_translation, level='error') _LC = functools.partial(_log_translation, level='critical') def install(domain, lazy=False): """Install a _() function using the given translation domain. Given a translation domain, install a _() function using gettext's install() function. The main difference from gettext.install() is that we allow overriding the default localedir (e.g. /usr/share/locale) using a translation-domain-specific environment variable (e.g. NOVA_LOCALEDIR). :param domain: the translation domain :param lazy: indicates whether or not to install the lazy _() function. The lazy _() introduces a way to do deferred translation of messages by installing a _ that builds Message objects, instead of strings, which can then be lazily translated into any available locale. """ if lazy: # NOTE(mrodden): Lazy gettext functionality. # # The following introduces a deferred way to do translations on # messages in OpenStack. We override the standard _() function # and % (format string) operation to build Message objects that can # later be translated when we have more information. def _lazy_gettext(msg): """Create and return a Message object. Lazy gettext function for a given domain, it is a factory method for a project/module to get a lazy gettext function for its own translation domain (i.e. nova, glance, cinder, etc.) Message encapsulates a string so that we can translate it later when needed. """ return Message(msg, domain=domain) from six import moves moves.builtins.__dict__['_'] = _lazy_gettext else: localedir = '%s_LOCALEDIR' % domain.upper() if six.PY3: gettext.install(domain, localedir=os.environ.get(localedir)) else: gettext.install(domain, localedir=os.environ.get(localedir), unicode=True) class Message(six.text_type): """A Message object is a unicode object that can be translated. Translation of Message is done explicitly using the translate() method. For all non-translation intents and purposes, a Message is simply unicode, and can be treated as such. """ def __new__(cls, msgid, msgtext=None, params=None, domain='keystone', *args): """Create a new Message object. In order for translation to work gettext requires a message ID, this msgid will be used as the base unicode text. It is also possible for the msgid and the base unicode text to be different by passing the msgtext parameter. """ # If the base msgtext is not given, we use the default translation # of the msgid (which is in English) just in case the system locale is # not English, so that the base text will be in that locale by default. if not msgtext: msgtext = Message._translate_msgid(msgid, domain) # We want to initialize the parent unicode with the actual object that # would have been plain unicode if 'Message' was not enabled. msg = super(Message, cls).__new__(cls, msgtext) msg.msgid = msgid msg.domain = domain msg.params = params return msg def translate(self, desired_locale=None): """Translate this message to the desired locale. :param desired_locale: The desired locale to translate the message to, if no locale is provided the message will be translated to the system's default locale. :returns: the translated message in unicode """ translated_message = Message._translate_msgid(self.msgid, self.domain, desired_locale) if self.params is None: # No need for more translation return translated_message # This Message object may have been formatted with one or more # Message objects as substitution arguments, given either as a single # argument, part of a tuple, or as one or more values in a dictionary. # When translating this Message we need to translate those Messages too translated_params = _translate_args(self.params, desired_locale) translated_message = translated_message % translated_params return translated_message @staticmethod def _translate_msgid(msgid, domain, desired_locale=None): if not desired_locale: system_locale = locale.getdefaultlocale() # If the system locale is not available to the runtime use English if not system_locale[0]: desired_locale = 'en_US' else: desired_locale = system_locale[0] locale_dir = os.environ.get(domain.upper() + '_LOCALEDIR') lang = gettext.translation(domain, localedir=locale_dir, languages=[desired_locale], fallback=True) if six.PY3: translator = lang.gettext else: translator = lang.ugettext translated_message = translator(msgid) return translated_message def __mod__(self, other): # When we mod a Message we want the actual operation to be performed # by the parent class (i.e. unicode()), the only thing we do here is # save the original msgid and the parameters in case of a translation params = self._sanitize_mod_params(other) unicode_mod = super(Message, self).__mod__(params) modded = Message(self.msgid, msgtext=unicode_mod, params=params, domain=self.domain) return modded def _sanitize_mod_params(self, other): """Sanitize the object being modded with this Message. - Add support for modding 'None' so translation supports it - Trim the modded object, which can be a large dictionary, to only those keys that would actually be used in a translation - Snapshot the object being modded, in case the message is translated, it will be used as it was when the Message was created """ if other is None: params = (other,) elif isinstance(other, dict): params = self._trim_dictionary_parameters(other) else: params = self._copy_param(other) return params def _trim_dictionary_parameters(self, dict_param): """Return a dict that only has matching entries in the msgid.""" # NOTE(luisg): Here we trim down the dictionary passed as parameters # to avoid carrying a lot of unnecessary weight around in the message # object, for example if someone passes in Message() % locals() but # only some params are used, and additionally we prevent errors for # non-deepcopyable objects by unicoding() them. # Look for %(param) keys in msgid; # Skip %% and deal with the case where % is first character on the line keys = re.findall('(?:[^%]|^)?%\((\w*)\)[a-z]', self.msgid) # If we don't find any %(param) keys but have a %s if not keys and re.findall('(?:[^%]|^)%[a-z]', self.msgid): # Apparently the full dictionary is the parameter params = self._copy_param(dict_param) else: params = {} # Save our existing parameters as defaults to protect # ourselves from losing values if we are called through an # (erroneous) chain that builds a valid Message with # arguments, and then does something like "msg % kwds" # where kwds is an empty dictionary. src = {} if isinstance(self.params, dict): src.update(self.params) src.update(dict_param) for key in keys: params[key] = self._copy_param(src[key]) return params def _copy_param(self, param): try: return copy.deepcopy(param) except TypeError: # Fallback to casting to unicode this will handle the # python code-like objects that can't be deep-copied return six.text_type(param) def __add__(self, other): msg = _('Message objects do not support addition.') raise TypeError(msg) def __radd__(self, other): return self.__add__(other) def __str__(self): # NOTE(luisg): Logging in python 2.6 tries to str() log records, # and it expects specifically a UnicodeError in order to proceed. msg = _('Message objects do not support str() because they may ' 'contain non-ascii characters. ' 'Please use unicode() or translate() instead.') raise UnicodeError(msg) def get_available_languages(domain): """Lists the available languages for the given translation domain. :param domain: the domain to get languages for """ if domain in _AVAILABLE_LANGUAGES: return copy.copy(_AVAILABLE_LANGUAGES[domain]) localedir = '%s_LOCALEDIR' % domain.upper() find = lambda x: gettext.find(domain, localedir=os.environ.get(localedir), languages=[x]) # NOTE(mrodden): en_US should always be available (and first in case # order matters) since our in-line message strings are en_US language_list = ['en_US'] # NOTE(luisg): Babel <1.0 used a function called list(), which was # renamed to locale_identifiers() in >=1.0, the requirements master list # requires >=0.9.6, uncapped, so defensively work with both. We can remove # this check when the master list updates to >=1.0, and update all projects list_identifiers = (getattr(localedata, 'list', None) or getattr(localedata, 'locale_identifiers')) locale_identifiers = list_identifiers() for i in locale_identifiers: if find(i) is not None: language_list.append(i) # NOTE(luisg): Babel>=1.0,<1.3 has a bug where some OpenStack supported # locales (e.g. 'zh_CN', and 'zh_TW') aren't supported even though they # are perfectly legitimate locales: # https://github.com/mitsuhiko/babel/issues/37 # In Babel 1.3 they fixed the bug and they support these locales, but # they are still not explicitly "listed" by locale_identifiers(). # That is why we add the locales here explicitly if necessary so that # they are listed as supported. aliases = {'zh': 'zh_CN', 'zh_Hant_HK': 'zh_HK', 'zh_Hant': 'zh_TW', 'fil': 'tl_PH'} for (locale, alias) in six.iteritems(aliases): if locale in language_list and alias not in language_list: language_list.append(alias) _AVAILABLE_LANGUAGES[domain] = language_list return copy.copy(language_list) def translate(obj, desired_locale=None): """Gets the translated unicode representation of the given object. If the object is not translatable it is returned as-is. If the locale is None the object is translated to the system locale. :param obj: the object to translate :param desired_locale: the locale to translate the message to, if None the default system locale will be used :returns: the translated object in unicode, or the original object if it could not be translated """ message = obj if not isinstance(message, Message): # If the object to translate is not already translatable, # let's first get its unicode representation message = six.text_type(obj) if isinstance(message, Message): # Even after unicoding() we still need to check if we are # running with translatable unicode before translating return message.translate(desired_locale) return obj def _translate_args(args, desired_locale=None): """Translates all the translatable elements of the given arguments object. This method is used for translating the translatable values in method arguments which include values of tuples or dictionaries. If the object is not a tuple or a dictionary the object itself is translated if it is translatable. If the locale is None the object is translated to the system locale. :param args: the args to translate :param desired_locale: the locale to translate the args to, if None the default system locale will be used :returns: a new args object with the translated contents of the original """ if isinstance(args, tuple): return tuple(translate(v, desired_locale) for v in args) if isinstance(args, dict): translated_dict = {} for (k, v) in six.iteritems(args): translated_v = translate(v, desired_locale) translated_dict[k] = translated_v return translated_dict return translate(args, desired_locale) class TranslationHandler(handlers.MemoryHandler): """Handler that translates records before logging them. The TranslationHandler takes a locale and a target logging.Handler object to forward LogRecord objects to after translating them. This handler depends on Message objects being logged, instead of regular strings. The handler can be configured declaratively in the logging.conf as follows: [handlers] keys = translatedlog, translator [handler_translatedlog] class = handlers.WatchedFileHandler args = ('/var/log/api-localized.log',) formatter = context [handler_translator] class = openstack.common.log.TranslationHandler target = translatedlog args = ('zh_CN',) If the specified locale is not available in the system, the handler will log in the default locale. """ def __init__(self, locale=None, target=None): """Initialize a TranslationHandler :param locale: locale to use for translating messages :param target: logging.Handler object to forward LogRecord objects to after translation """ # NOTE(luisg): In order to allow this handler to be a wrapper for # other handlers, such as a FileHandler, and still be able to # configure it using logging.conf, this handler has to extend # MemoryHandler because only the MemoryHandlers' logging.conf # parsing is implemented such that it accepts a target handler. handlers.MemoryHandler.__init__(self, capacity=0, target=target) self.locale = locale def setFormatter(self, fmt): self.target.setFormatter(fmt) def emit(self, record): # We save the message from the original record to restore it # after translation, so other handlers are not affected by this original_msg = record.msg original_args = record.args try: self._translate_and_log_record(record) finally: record.msg = original_msg record.args = original_args def _translate_and_log_record(self, record): record.msg = translate(record.msg, self.locale) # In addition to translating the message, we also need to translate # arguments that were passed to the log method that were not part # of the main message e.g., log.info(_('Some message %s'), this_one)) record.args = _translate_args(record.args, self.locale) self.target.emit(record) keystone-2014.1/keystone/openstack/common/log.py0000664000175400017540000006223012323716267023067 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """Openstack logging handler. This module adds to logging functionality by adding the option to specify a context object when calling the various log methods. If the context object is not specified, default formatting is used. Additionally, an instance uuid may be passed as part of the log message, which is intended to make it easier for admins to find messages related to a specific instance. It also allows setting of formatting information through conf. """ import inspect import itertools import logging import logging.config import logging.handlers import os import re import sys import traceback from oslo.config import cfg import six from six import moves from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone.openstack.common import jsonutils from keystone.openstack.common import local _DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" _SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password'] # NOTE(ldbragst): Let's build a list of regex objects using the list of # _SANITIZE_KEYS we already have. This way, we only have to add the new key # to the list of _SANITIZE_KEYS and we can generate regular expressions # for XML and JSON automatically. _SANITIZE_PATTERNS = [] _FORMAT_PATTERNS = [r'(%(key)s\s*[=]\s*[\"\']).*?([\"\'])', r'(<%(key)s>).*?()', r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])', r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])'] for key in _SANITIZE_KEYS: for pattern in _FORMAT_PATTERNS: reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) _SANITIZE_PATTERNS.append(reg_ex) common_cli_opts = [ cfg.BoolOpt('debug', short='d', default=False, help='Print debugging output (set logging level to ' 'DEBUG instead of default WARNING level).'), cfg.BoolOpt('verbose', short='v', default=False, help='Print more verbose output (set logging level to ' 'INFO instead of default WARNING level).'), ] logging_cli_opts = [ cfg.StrOpt('log-config-append', metavar='PATH', deprecated_name='log-config', help='The name of logging configuration file. It does not ' 'disable existing loggers, but just appends specified ' 'logging configuration to any other existing logging ' 'options. Please see the Python logging module ' 'documentation for details on logging configuration ' 'files.'), cfg.StrOpt('log-format', default=None, metavar='FORMAT', help='DEPRECATED. ' 'A logging.Formatter log message format string which may ' 'use any of the available logging.LogRecord attributes. ' 'This option is deprecated. Please use ' 'logging_context_format_string and ' 'logging_default_format_string instead.'), cfg.StrOpt('log-date-format', default=_DEFAULT_LOG_DATE_FORMAT, metavar='DATE_FORMAT', help='Format string for %%(asctime)s in log records. ' 'Default: %(default)s'), cfg.StrOpt('log-file', metavar='PATH', deprecated_name='logfile', help='(Optional) Name of log file to output to. ' 'If no default is set, logging will go to stdout.'), cfg.StrOpt('log-dir', deprecated_name='logdir', help='(Optional) The base directory used for relative ' '--log-file paths'), cfg.BoolOpt('use-syslog', default=False, help='Use syslog for logging. ' 'Existing syslog format is DEPRECATED during I, ' 'and then will be changed in J to honor RFC5424'), cfg.BoolOpt('use-syslog-rfc-format', # TODO(bogdando) remove or use True after existing # syslog format deprecation in J default=False, help='(Optional) Use syslog rfc5424 format for logging. ' 'If enabled, will add APP-NAME (RFC5424) before the ' 'MSG part of the syslog message. The old format ' 'without APP-NAME is deprecated in I, ' 'and will be removed in J.'), cfg.StrOpt('syslog-log-facility', default='LOG_USER', help='Syslog facility to receive log lines') ] generic_log_opts = [ cfg.BoolOpt('use_stderr', default=True, help='Log output to standard error') ] log_opts = [ cfg.StrOpt('logging_context_format_string', default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' '%(name)s [%(request_id)s %(user_identity)s] ' '%(instance)s%(message)s', help='Format string to use for log messages with context'), cfg.StrOpt('logging_default_format_string', default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s ' '%(name)s [-] %(instance)s%(message)s', help='Format string to use for log messages without context'), cfg.StrOpt('logging_debug_format_suffix', default='%(funcName)s %(pathname)s:%(lineno)d', help='Data to append to log format when level is DEBUG'), cfg.StrOpt('logging_exception_prefix', default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s ' '%(instance)s', help='Prefix each line of exception output with this format'), cfg.ListOpt('default_log_levels', default=[ 'amqp=WARN', 'amqplib=WARN', 'boto=WARN', 'qpid=WARN', 'sqlalchemy=WARN', 'suds=INFO', 'iso8601=WARN', 'requests.packages.urllib3.connectionpool=WARN' ], help='List of logger=LEVEL pairs'), cfg.BoolOpt('publish_errors', default=False, help='Publish error events'), cfg.BoolOpt('fatal_deprecations', default=False, help='Make deprecations fatal'), # NOTE(mikal): there are two options here because sometimes we are handed # a full instance (and could include more information), and other times we # are just handed a UUID for the instance. cfg.StrOpt('instance_format', default='[instance: %(uuid)s] ', help='If an instance is passed with the log message, format ' 'it like this'), cfg.StrOpt('instance_uuid_format', default='[instance: %(uuid)s] ', help='If an instance UUID is passed with the log message, ' 'format it like this'), ] CONF = cfg.CONF CONF.register_cli_opts(common_cli_opts) CONF.register_cli_opts(logging_cli_opts) CONF.register_opts(generic_log_opts) CONF.register_opts(log_opts) # our new audit level # NOTE(jkoelker) Since we synthesized an audit level, make the logging # module aware of it so it acts like other levels. logging.AUDIT = logging.INFO + 1 logging.addLevelName(logging.AUDIT, 'AUDIT') try: NullHandler = logging.NullHandler except AttributeError: # NOTE(jkoelker) NullHandler added in Python 2.7 class NullHandler(logging.Handler): def handle(self, record): pass def emit(self, record): pass def createLock(self): self.lock = None def _dictify_context(context): if context is None: return None if not isinstance(context, dict) and getattr(context, 'to_dict', None): context = context.to_dict() return context def _get_binary_name(): return os.path.basename(inspect.stack()[-1][1]) def _get_log_file_path(binary=None): logfile = CONF.log_file logdir = CONF.log_dir if logfile and not logdir: return logfile if logfile and logdir: return os.path.join(logdir, logfile) if logdir: binary = binary or _get_binary_name() return '%s.log' % (os.path.join(logdir, binary),) return None def mask_password(message, secret="***"): """Replace password with 'secret' in message. :param message: The string which includes security information. :param secret: value with which to replace passwords. :returns: The unicode value of message with the password fields masked. For example: >>> mask_password("'adminPass' : 'aaaaa'") "'adminPass' : '***'" >>> mask_password("'admin_pass' : 'aaaaa'") "'admin_pass' : '***'" >>> mask_password('"password" : "aaaaa"') '"password" : "***"' >>> mask_password("'original_password' : 'aaaaa'") "'original_password' : '***'" >>> mask_password("u'original_password' : u'aaaaa'") "u'original_password' : u'***'" """ message = six.text_type(message) # NOTE(ldbragst): Check to see if anything in message contains any key # specified in _SANITIZE_KEYS, if not then just return the message since # we don't have to mask any passwords. if not any(key in message for key in _SANITIZE_KEYS): return message secret = r'\g<1>' + secret + r'\g<2>' for pattern in _SANITIZE_PATTERNS: message = re.sub(pattern, secret, message) return message class BaseLoggerAdapter(logging.LoggerAdapter): def audit(self, msg, *args, **kwargs): self.log(logging.AUDIT, msg, *args, **kwargs) class LazyAdapter(BaseLoggerAdapter): def __init__(self, name='unknown', version='unknown'): self._logger = None self.extra = {} self.name = name self.version = version @property def logger(self): if not self._logger: self._logger = getLogger(self.name, self.version) return self._logger class ContextAdapter(BaseLoggerAdapter): warn = logging.LoggerAdapter.warning def __init__(self, logger, project_name, version_string): self.logger = logger self.project = project_name self.version = version_string self._deprecated_messages_sent = dict() @property def handlers(self): return self.logger.handlers def deprecated(self, msg, *args, **kwargs): """Call this method when a deprecated feature is used. If the system is configured for fatal deprecations then the message is logged at the 'critical' level and :class:`DeprecatedConfig` will be raised. Otherwise, the message will be logged (once) at the 'warn' level. :raises: :class:`DeprecatedConfig` if the system is configured for fatal deprecations. """ stdmsg = _("Deprecated: %s") % msg if CONF.fatal_deprecations: self.critical(stdmsg, *args, **kwargs) raise DeprecatedConfig(msg=stdmsg) # Using a list because a tuple with dict can't be stored in a set. sent_args = self._deprecated_messages_sent.setdefault(msg, list()) if args in sent_args: # Already logged this message, so don't log it again. return sent_args.append(args) self.warn(stdmsg, *args, **kwargs) def process(self, msg, kwargs): # NOTE(mrodden): catch any Message/other object and # coerce to unicode before they can get # to the python logging and possibly # cause string encoding trouble if not isinstance(msg, six.string_types): msg = six.text_type(msg) if 'extra' not in kwargs: kwargs['extra'] = {} extra = kwargs['extra'] context = kwargs.pop('context', None) if not context: context = getattr(local.store, 'context', None) if context: extra.update(_dictify_context(context)) instance = kwargs.pop('instance', None) instance_uuid = (extra.get('instance_uuid', None) or kwargs.pop('instance_uuid', None)) instance_extra = '' if instance: instance_extra = CONF.instance_format % instance elif instance_uuid: instance_extra = (CONF.instance_uuid_format % {'uuid': instance_uuid}) extra['instance'] = instance_extra extra.setdefault('user_identity', kwargs.pop('user_identity', None)) extra['project'] = self.project extra['version'] = self.version extra['extra'] = extra.copy() return msg, kwargs class JSONFormatter(logging.Formatter): def __init__(self, fmt=None, datefmt=None): # NOTE(jkoelker) we ignore the fmt argument, but its still there # since logging.config.fileConfig passes it. self.datefmt = datefmt def formatException(self, ei, strip_newlines=True): lines = traceback.format_exception(*ei) if strip_newlines: lines = [moves.filter( lambda x: x, line.rstrip().splitlines()) for line in lines] lines = list(itertools.chain(*lines)) return lines def format(self, record): message = {'message': record.getMessage(), 'asctime': self.formatTime(record, self.datefmt), 'name': record.name, 'msg': record.msg, 'args': record.args, 'levelname': record.levelname, 'levelno': record.levelno, 'pathname': record.pathname, 'filename': record.filename, 'module': record.module, 'lineno': record.lineno, 'funcname': record.funcName, 'created': record.created, 'msecs': record.msecs, 'relative_created': record.relativeCreated, 'thread': record.thread, 'thread_name': record.threadName, 'process_name': record.processName, 'process': record.process, 'traceback': None} if hasattr(record, 'extra'): message['extra'] = record.extra if record.exc_info: message['traceback'] = self.formatException(record.exc_info) return jsonutils.dumps(message) def _create_logging_excepthook(product_name): def logging_excepthook(exc_type, value, tb): extra = {} if CONF.verbose or CONF.debug: extra['exc_info'] = (exc_type, value, tb) getLogger(product_name).critical( "".join(traceback.format_exception_only(exc_type, value)), **extra) return logging_excepthook class LogConfigError(Exception): message = _('Error loading logging config %(log_config)s: %(err_msg)s') def __init__(self, log_config, err_msg): self.log_config = log_config self.err_msg = err_msg def __str__(self): return self.message % dict(log_config=self.log_config, err_msg=self.err_msg) def _load_log_config(log_config_append): try: logging.config.fileConfig(log_config_append, disable_existing_loggers=False) except moves.configparser.Error as exc: raise LogConfigError(log_config_append, str(exc)) def setup(product_name, version='unknown'): """Setup logging.""" if CONF.log_config_append: _load_log_config(CONF.log_config_append) else: _setup_logging_from_conf(product_name, version) sys.excepthook = _create_logging_excepthook(product_name) def set_defaults(logging_context_format_string): cfg.set_defaults(log_opts, logging_context_format_string= logging_context_format_string) def _find_facility_from_conf(): facility_names = logging.handlers.SysLogHandler.facility_names facility = getattr(logging.handlers.SysLogHandler, CONF.syslog_log_facility, None) if facility is None and CONF.syslog_log_facility in facility_names: facility = facility_names.get(CONF.syslog_log_facility) if facility is None: valid_facilities = facility_names.keys() consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7'] valid_facilities.extend(consts) raise TypeError(_('syslog facility must be one of: %s') % ', '.join("'%s'" % fac for fac in valid_facilities)) return facility class RFCSysLogHandler(logging.handlers.SysLogHandler): def __init__(self, *args, **kwargs): self.binary_name = _get_binary_name() super(RFCSysLogHandler, self).__init__(*args, **kwargs) def format(self, record): msg = super(RFCSysLogHandler, self).format(record) msg = self.binary_name + ' ' + msg return msg def _setup_logging_from_conf(project, version): log_root = getLogger(None).logger for handler in log_root.handlers: log_root.removeHandler(handler) if CONF.use_syslog: facility = _find_facility_from_conf() # TODO(bogdando) use the format provided by RFCSysLogHandler # after existing syslog format deprecation in J if CONF.use_syslog_rfc_format: syslog = RFCSysLogHandler(address='/dev/log', facility=facility) else: syslog = logging.handlers.SysLogHandler(address='/dev/log', facility=facility) log_root.addHandler(syslog) logpath = _get_log_file_path() if logpath: filelog = logging.handlers.WatchedFileHandler(logpath) log_root.addHandler(filelog) if CONF.use_stderr: streamlog = ColorHandler() log_root.addHandler(streamlog) elif not logpath: # pass sys.stdout as a positional argument # python2.6 calls the argument strm, in 2.7 it's stream streamlog = logging.StreamHandler(sys.stdout) log_root.addHandler(streamlog) if CONF.publish_errors: handler = importutils.import_object( "keystone.openstack.common.log_handler.PublishErrorsHandler", logging.ERROR) log_root.addHandler(handler) datefmt = CONF.log_date_format for handler in log_root.handlers: # NOTE(alaski): CONF.log_format overrides everything currently. This # should be deprecated in favor of context aware formatting. if CONF.log_format: handler.setFormatter(logging.Formatter(fmt=CONF.log_format, datefmt=datefmt)) log_root.info('Deprecated: log_format is now deprecated and will ' 'be removed in the next release') else: handler.setFormatter(ContextFormatter(project=project, version=version, datefmt=datefmt)) if CONF.debug: log_root.setLevel(logging.DEBUG) elif CONF.verbose: log_root.setLevel(logging.INFO) else: log_root.setLevel(logging.WARNING) for pair in CONF.default_log_levels: mod, _sep, level_name = pair.partition('=') level = logging.getLevelName(level_name) logger = logging.getLogger(mod) logger.setLevel(level) _loggers = {} def getLogger(name='unknown', version='unknown'): if name not in _loggers: _loggers[name] = ContextAdapter(logging.getLogger(name), name, version) return _loggers[name] def getLazyLogger(name='unknown', version='unknown'): """Returns lazy logger. Creates a pass-through logger that does not create the real logger until it is really needed and delegates all calls to the real logger once it is created. """ return LazyAdapter(name, version) class WritableLogger(object): """A thin wrapper that responds to `write` and logs.""" def __init__(self, logger, level=logging.INFO): self.logger = logger self.level = level def write(self, msg): self.logger.log(self.level, msg.rstrip()) class ContextFormatter(logging.Formatter): """A context.RequestContext aware formatter configured through flags. The flags used to set format strings are: logging_context_format_string and logging_default_format_string. You can also specify logging_debug_format_suffix to append extra formatting if the log level is debug. For information about what variables are available for the formatter see: http://docs.python.org/library/logging.html#formatter If available, uses the context value stored in TLS - local.store.context """ def __init__(self, *args, **kwargs): """Initialize ContextFormatter instance Takes additional keyword arguments which can be used in the message format string. :keyword project: project name :type project: string :keyword version: project version :type version: string """ self.project = kwargs.pop('project', 'unknown') self.version = kwargs.pop('version', 'unknown') logging.Formatter.__init__(self, *args, **kwargs) def format(self, record): """Uses contextstring if request_id is set, otherwise default.""" # store project info record.project = self.project record.version = self.version # store request info context = getattr(local.store, 'context', None) if context: d = _dictify_context(context) for k, v in d.items(): setattr(record, k, v) # NOTE(sdague): default the fancier formatting params # to an empty string so we don't throw an exception if # they get used for key in ('instance', 'color'): if key not in record.__dict__: record.__dict__[key] = '' if record.__dict__.get('request_id', None): self._fmt = CONF.logging_context_format_string else: self._fmt = CONF.logging_default_format_string if (record.levelno == logging.DEBUG and CONF.logging_debug_format_suffix): self._fmt += " " + CONF.logging_debug_format_suffix # Cache this on the record, Logger will respect our formatted copy if record.exc_info: record.exc_text = self.formatException(record.exc_info, record) return logging.Formatter.format(self, record) def formatException(self, exc_info, record=None): """Format exception output with CONF.logging_exception_prefix.""" if not record: return logging.Formatter.formatException(self, exc_info) stringbuffer = moves.StringIO() traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], None, stringbuffer) lines = stringbuffer.getvalue().split('\n') stringbuffer.close() if CONF.logging_exception_prefix.find('%(asctime)') != -1: record.asctime = self.formatTime(record, self.datefmt) formatted_lines = [] for line in lines: pl = CONF.logging_exception_prefix % record.__dict__ fl = '%s%s' % (pl, line) formatted_lines.append(fl) return '\n'.join(formatted_lines) class ColorHandler(logging.StreamHandler): LEVEL_COLORS = { logging.DEBUG: '\033[00;32m', # GREEN logging.INFO: '\033[00;36m', # CYAN logging.AUDIT: '\033[01;36m', # BOLD CYAN logging.WARN: '\033[01;33m', # BOLD YELLOW logging.ERROR: '\033[01;31m', # BOLD RED logging.CRITICAL: '\033[01;31m', # BOLD RED } def format(self, record): record.color = self.LEVEL_COLORS[record.levelno] return logging.StreamHandler.format(self, record) class DeprecatedConfig(Exception): message = _("Fatal call to deprecated config: %(msg)s") def __init__(self, msg): super(Exception, self).__init__(self.message % dict(msg=msg)) keystone-2014.1/keystone/openstack/common/service.py0000664000175400017540000003250612323716267023751 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 Justin Santa Barbara # All Rights Reserved. # # 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. """Generic Node base class for all workers that run on hosts.""" import errno import logging as std_logging import os import random import signal import sys import time import eventlet from eventlet import event from oslo.config import cfg from keystone.openstack.common import eventlet_backdoor from keystone.openstack.common.gettextutils import _ # noqa from keystone.openstack.common import importutils from keystone.openstack.common import log as logging from keystone.openstack.common import threadgroup rpc = importutils.try_import('keystone.openstack.common.rpc') CONF = cfg.CONF LOG = logging.getLogger(__name__) def _sighup_supported(): return hasattr(signal, 'SIGHUP') def _is_sighup(signo): return _sighup_supported() and signo == signal.SIGHUP def _signo_to_signame(signo): signals = {signal.SIGTERM: 'SIGTERM', signal.SIGINT: 'SIGINT'} if _sighup_supported(): signals[signal.SIGHUP] = 'SIGHUP' return signals[signo] def _set_signals_handler(handler): signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGINT, handler) if _sighup_supported(): signal.signal(signal.SIGHUP, handler) class Launcher(object): """Launch one or more services and wait for them to complete.""" def __init__(self): """Initialize the service launcher. :returns: None """ self.services = Services() self.backdoor_port = eventlet_backdoor.initialize_if_enabled() def launch_service(self, service): """Load and start the given service. :param service: The service you would like to start. :returns: None """ service.backdoor_port = self.backdoor_port self.services.add(service) def stop(self): """Stop all services which are currently running. :returns: None """ self.services.stop() def wait(self): """Waits until all services have been stopped, and then returns. :returns: None """ self.services.wait() def restart(self): """Reload config files and restart service. :returns: None """ cfg.CONF.reload_config_files() self.services.restart() class SignalExit(SystemExit): def __init__(self, signo, exccode=1): super(SignalExit, self).__init__(exccode) self.signo = signo class ServiceLauncher(Launcher): def _handle_signal(self, signo, frame): # Allow the process to be killed again and die from natural causes _set_signals_handler(signal.SIG_DFL) raise SignalExit(signo) def handle_signal(self): _set_signals_handler(self._handle_signal) def _wait_for_exit_or_signal(self, ready_callback=None): status = None signo = 0 LOG.debug(_('Full set of CONF:')) CONF.log_opt_values(LOG, std_logging.DEBUG) try: if ready_callback: ready_callback() super(ServiceLauncher, self).wait() except SignalExit as exc: signame = _signo_to_signame(exc.signo) LOG.info(_('Caught %s, exiting'), signame) status = exc.code signo = exc.signo except SystemExit as exc: status = exc.code finally: self.stop() if rpc: try: rpc.cleanup() except Exception: # We're shutting down, so it doesn't matter at this point. LOG.exception(_('Exception during rpc cleanup.')) return status, signo def wait(self, ready_callback=None): while True: self.handle_signal() status, signo = self._wait_for_exit_or_signal(ready_callback) if not _is_sighup(signo): return status self.restart() class ServiceWrapper(object): def __init__(self, service, workers): self.service = service self.workers = workers self.children = set() self.forktimes = [] class ProcessLauncher(object): def __init__(self): self.children = {} self.sigcaught = None self.running = True rfd, self.writepipe = os.pipe() self.readpipe = eventlet.greenio.GreenPipe(rfd, 'r') self.handle_signal() def handle_signal(self): _set_signals_handler(self._handle_signal) def _handle_signal(self, signo, frame): self.sigcaught = signo self.running = False # Allow the process to be killed again and die from natural causes _set_signals_handler(signal.SIG_DFL) def _pipe_watcher(self): # This will block until the write end is closed when the parent # dies unexpectedly self.readpipe.read() LOG.info(_('Parent process has died unexpectedly, exiting')) sys.exit(1) def _child_process_handle_signal(self): # Setup child signal handlers differently def _sigterm(*args): signal.signal(signal.SIGTERM, signal.SIG_DFL) raise SignalExit(signal.SIGTERM) def _sighup(*args): signal.signal(signal.SIGHUP, signal.SIG_DFL) raise SignalExit(signal.SIGHUP) signal.signal(signal.SIGTERM, _sigterm) if _sighup_supported(): signal.signal(signal.SIGHUP, _sighup) # Block SIGINT and let the parent send us a SIGTERM signal.signal(signal.SIGINT, signal.SIG_IGN) def _child_wait_for_exit_or_signal(self, launcher): status = 0 signo = 0 # NOTE(johannes): All exceptions are caught to ensure this # doesn't fallback into the loop spawning children. It would # be bad for a child to spawn more children. try: launcher.wait() except SignalExit as exc: signame = _signo_to_signame(exc.signo) LOG.info(_('Caught %s, exiting'), signame) status = exc.code signo = exc.signo except SystemExit as exc: status = exc.code except BaseException: LOG.exception(_('Unhandled exception')) status = 2 finally: launcher.stop() return status, signo def _child_process(self, service): self._child_process_handle_signal() # Reopen the eventlet hub to make sure we don't share an epoll # fd with parent and/or siblings, which would be bad eventlet.hubs.use_hub() # Close write to ensure only parent has it open os.close(self.writepipe) # Create greenthread to watch for parent to close pipe eventlet.spawn_n(self._pipe_watcher) # Reseed random number generator random.seed() launcher = Launcher() launcher.launch_service(service) return launcher def _start_child(self, wrap): if len(wrap.forktimes) > wrap.workers: # Limit ourselves to one process a second (over the period of # number of workers * 1 second). This will allow workers to # start up quickly but ensure we don't fork off children that # die instantly too quickly. if time.time() - wrap.forktimes[0] < wrap.workers: LOG.info(_('Forking too fast, sleeping')) time.sleep(1) wrap.forktimes.pop(0) wrap.forktimes.append(time.time()) pid = os.fork() if pid == 0: launcher = self._child_process(wrap.service) while True: self._child_process_handle_signal() status, signo = self._child_wait_for_exit_or_signal(launcher) if not _is_sighup(signo): break launcher.restart() os._exit(status) LOG.info(_('Started child %d'), pid) wrap.children.add(pid) self.children[pid] = wrap return pid def launch_service(self, service, workers=1): wrap = ServiceWrapper(service, workers) LOG.info(_('Starting %d workers'), wrap.workers) while self.running and len(wrap.children) < wrap.workers: self._start_child(wrap) def _wait_child(self): try: # Don't block if no child processes have exited pid, status = os.waitpid(0, os.WNOHANG) if not pid: return None except OSError as exc: if exc.errno not in (errno.EINTR, errno.ECHILD): raise return None if os.WIFSIGNALED(status): sig = os.WTERMSIG(status) LOG.info(_('Child %(pid)d killed by signal %(sig)d'), dict(pid=pid, sig=sig)) else: code = os.WEXITSTATUS(status) LOG.info(_('Child %(pid)s exited with status %(code)d'), dict(pid=pid, code=code)) if pid not in self.children: LOG.warning(_('pid %d not in child list'), pid) return None wrap = self.children.pop(pid) wrap.children.remove(pid) return wrap def _respawn_children(self): while self.running: wrap = self._wait_child() if not wrap: # Yield to other threads if no children have exited # Sleep for a short time to avoid excessive CPU usage # (see bug #1095346) eventlet.greenthread.sleep(.01) continue while self.running and len(wrap.children) < wrap.workers: self._start_child(wrap) def wait(self): """Loop waiting on children to die and respawning as necessary.""" LOG.debug(_('Full set of CONF:')) CONF.log_opt_values(LOG, std_logging.DEBUG) while True: self.handle_signal() self._respawn_children() if self.sigcaught: signame = _signo_to_signame(self.sigcaught) LOG.info(_('Caught %s, stopping children'), signame) if not _is_sighup(self.sigcaught): break for pid in self.children: os.kill(pid, signal.SIGHUP) self.running = True self.sigcaught = None for pid in self.children: try: os.kill(pid, signal.SIGTERM) except OSError as exc: if exc.errno != errno.ESRCH: raise # Wait for children to die if self.children: LOG.info(_('Waiting on %d children to exit'), len(self.children)) while self.children: self._wait_child() class Service(object): """Service object for binaries running on hosts.""" def __init__(self, threads=1000): self.tg = threadgroup.ThreadGroup(threads) # signal that the service is done shutting itself down: self._done = event.Event() def reset(self): # NOTE(Fengqian): docs for Event.reset() recommend against using it self._done = event.Event() def start(self): pass def stop(self): self.tg.stop() self.tg.wait() # Signal that service cleanup is done: if not self._done.ready(): self._done.send() def wait(self): self._done.wait() class Services(object): def __init__(self): self.services = [] self.tg = threadgroup.ThreadGroup() self.done = event.Event() def add(self, service): self.services.append(service) self.tg.add_thread(self.run_service, service, self.done) def stop(self): # wait for graceful shutdown of services: for service in self.services: service.stop() service.wait() # Each service has performed cleanup, now signal that the run_service # wrapper threads can now die: if not self.done.ready(): self.done.send() # reap threads: self.tg.stop() def wait(self): self.tg.wait() def restart(self): self.stop() self.done = event.Event() for restart_service in self.services: restart_service.reset() self.tg.add_thread(self.run_service, restart_service, self.done) @staticmethod def run_service(service, done): """Service start wrapper. :param service: service to run :param done: event to wait on until a shutdown is triggered :returns: None """ service.start() done.wait() def launch(service, workers=None): if workers: launcher = ProcessLauncher() launcher.launch_service(service, workers=workers) else: launcher = ServiceLauncher() launcher.launch_service(service) return launcher keystone-2014.1/keystone/openstack/common/exception.py0000664000175400017540000000636412323716267024312 0ustar jenkinsjenkins00000000000000# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # 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. """ Exceptions common to OpenStack projects """ import logging from keystone.openstack.common.gettextutils import _ # noqa _FATAL_EXCEPTION_FORMAT_ERRORS = False class Error(Exception): def __init__(self, message=None): super(Error, self).__init__(message) class ApiError(Error): def __init__(self, message='Unknown', code='Unknown'): self.api_message = message self.code = code super(ApiError, self).__init__('%s: %s' % (code, message)) class NotFound(Error): pass class UnknownScheme(Error): msg_fmt = "Unknown scheme '%s' found in URI" def __init__(self, scheme): msg = self.msg_fmt % scheme super(UnknownScheme, self).__init__(msg) class BadStoreUri(Error): msg_fmt = "The Store URI %s was malformed. Reason: %s" def __init__(self, uri, reason): msg = self.msg_fmt % (uri, reason) super(BadStoreUri, self).__init__(msg) class Duplicate(Error): pass class NotAuthorized(Error): pass class NotEmpty(Error): pass class Invalid(Error): pass class BadInputError(Exception): """Error resulting from a client sending bad input to a server""" pass class MissingArgumentError(Error): pass class DatabaseMigrationError(Error): pass class ClientConnectionError(Exception): """Error resulting from a client connecting to a server""" pass def wrap_exception(f): def _wrap(*args, **kw): try: return f(*args, **kw) except Exception as e: if not isinstance(e, Error): logging.exception(_('Uncaught exception')) raise Error(str(e)) raise _wrap.func_name = f.func_name return _wrap class OpenstackException(Exception): """Base Exception class. To correctly use this class, inherit from it and define a 'msg_fmt' property. That message will get printf'd with the keyword arguments provided to the constructor. """ msg_fmt = "An unknown exception occurred" def __init__(self, **kwargs): try: self._error_string = self.msg_fmt % kwargs except Exception: if _FATAL_EXCEPTION_FORMAT_ERRORS: raise else: # at least get the core message out if something happened self._error_string = self.msg_fmt def __str__(self): return self._error_string class MalformedRequestBody(OpenstackException): msg_fmt = "Malformed message body: %(reason)s" class InvalidContentType(OpenstackException): msg_fmt = "Invalid content type %(content_type)s" keystone-2014.1/keystone/openstack/common/excutils.py0000664000175400017540000000720312323716267024145 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # Copyright 2012, 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. """ Exception related utilities. """ import logging import sys import time import traceback import six from keystone.openstack.common.gettextutils import _ # noqa class save_and_reraise_exception(object): """Save current exception, run some code and then re-raise. In some cases the exception context can be cleared, resulting in None being attempted to be re-raised after an exception handler is run. This can happen when eventlet switches greenthreads or when running an exception handler, code raises and catches an exception. In both cases the exception context will be cleared. To work around this, we save the exception state, run handler code, and then re-raise the original exception. If another exception occurs, the saved exception is logged and the new exception is re-raised. In some cases the caller may not want to re-raise the exception, and for those circumstances this context provides a reraise flag that can be used to suppress the exception. For example:: except Exception: with save_and_reraise_exception() as ctxt: decide_if_need_reraise() if not should_be_reraised: ctxt.reraise = False """ def __init__(self): self.reraise = True def __enter__(self): self.type_, self.value, self.tb, = sys.exc_info() return self def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is not None: logging.error(_('Original exception being dropped: %s'), traceback.format_exception(self.type_, self.value, self.tb)) return False if self.reraise: six.reraise(self.type_, self.value, self.tb) def forever_retry_uncaught_exceptions(infunc): def inner_func(*args, **kwargs): last_log_time = 0 last_exc_message = None exc_count = 0 while True: try: return infunc(*args, **kwargs) except Exception as exc: this_exc_message = six.u(str(exc)) if this_exc_message == last_exc_message: exc_count += 1 else: exc_count = 1 # Do not log any more frequently than once a minute unless # the exception message changes cur_time = int(time.time()) if (cur_time - last_log_time > 60 or this_exc_message != last_exc_message): logging.exception( _('Unexpected exception occurred %d time(s)... ' 'retrying.') % exc_count) last_log_time = cur_time last_exc_message = this_exc_message exc_count = 0 # This should be a very rare event. In case it isn't, do # a sleep. time.sleep(1) return inner_func keystone-2014.1/keystone/openstack/common/versionutils.py0000664000175400017540000001153612323716267025057 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 OpenStack Foundation # All Rights Reserved. # # 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. """ Helpers for comparing version strings. """ import functools import pkg_resources from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log as logging LOG = logging.getLogger(__name__) class deprecated(object): """A decorator to mark callables as deprecated. deprecated logs a deprecation message when the callable it decorates is used. The message will include the release where the callable was deprecated, the release where is may be removed and possibly an optional replacement. Examples: 1. Specifing the required deprecated release >>> @deprecated(as_of=deprecated.ICEHOUSE) ... def a(): pass 2. Specifing a replacement: >>> @deprecated(as_of=deprecated.ICEHOUSE, in_favor_of='f()') ... def b(): pass 3. Specifying the release where the functionality may be removed: >>> @deprecated(as_of=deprecated.ICEHOUSE, remove_in=+1) ... def c(): pass """ FOLSOM = 'F' GRIZZLY = 'G' HAVANA = 'H' ICEHOUSE = 'I' _RELEASES = { 'F': 'Folsom', 'G': 'Grizzly', 'H': 'Havana', 'I': 'Icehouse', } _deprecated_msg_with_alternative = _( '%(what)s is deprecated as of %(as_of)s in favor of ' '%(in_favor_of)s and may be removed in %(remove_in)s.') _deprecated_msg_no_alternative = _( '%(what)s is deprecated as of %(as_of)s and may be ' 'removed in %(remove_in)s. It will not be superseded.') def __init__(self, as_of, in_favor_of=None, remove_in=2, what=None): """Initialize decorator :param as_of: the release deprecating the callable. Constants are define in this class for convenience. :param in_favor_of: the replacement for the callable (optional) :param remove_in: an integer specifying how many releases to wait before removing (default: 2) :param what: name of the thing being deprecated (default: the callable's name) """ self.as_of = as_of self.in_favor_of = in_favor_of self.remove_in = remove_in self.what = what def __call__(self, func): if not self.what: self.what = func.__name__ + '()' @functools.wraps(func) def wrapped(*args, **kwargs): msg, details = self._build_message() LOG.deprecated(msg, details) return func(*args, **kwargs) return wrapped def _get_safe_to_remove_release(self, release): # TODO(dstanek): this method will have to be reimplemented once # when we get to the X release because once we get to the Y # release, what is Y+2? new_release = chr(ord(release) + self.remove_in) if new_release in self._RELEASES: return self._RELEASES[new_release] else: return new_release def _build_message(self): details = dict(what=self.what, as_of=self._RELEASES[self.as_of], remove_in=self._get_safe_to_remove_release(self.as_of)) if self.in_favor_of: details['in_favor_of'] = self.in_favor_of msg = self._deprecated_msg_with_alternative else: msg = self._deprecated_msg_no_alternative return msg, details def is_compatible(requested_version, current_version, same_major=True): """Determine whether `requested_version` is satisfied by `current_version`; in other words, `current_version` is >= `requested_version`. :param requested_version: version to check for compatibility :param current_version: version to check against :param same_major: if True, the major version must be identical between `requested_version` and `current_version`. This is used when a major-version difference indicates incompatibility between the two versions. Since this is the common-case in practice, the default is True. :returns: True if compatible, False if not """ requested_parts = pkg_resources.parse_version(requested_version) current_parts = pkg_resources.parse_version(current_version) if same_major and (requested_parts[0] != current_parts[0]): return False return current_parts >= requested_parts keystone-2014.1/keystone/openstack/common/local.py0000664000175400017540000000321512323716267023376 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # 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. """Local storage of variables using weak references""" import threading import weakref class WeakLocal(threading.local): def __getattribute__(self, attr): rval = super(WeakLocal, self).__getattribute__(attr) if rval: # NOTE(mikal): this bit is confusing. What is stored is a weak # reference, not the value itself. We therefore need to lookup # the weak reference and return the inner value here. rval = rval() return rval def __setattr__(self, attr, value): value = weakref.ref(value) return super(WeakLocal, self).__setattr__(attr, value) # NOTE(mikal): the name "store" should be deprecated in the future store = WeakLocal() # A "weak" store uses weak references and allows an object to fall out of scope # when it falls out of scope in the code that uses the thread local storage. A # "strong" store will hold a reference to the object so that it never falls out # of scope. weak_store = WeakLocal() strong_store = threading.local() keystone-2014.1/keystone/openstack/common/test.py0000664000175400017540000000360212323716267023263 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # All Rights Reserved. # # 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. """Common utilities used in testing""" import os import fixtures import testtools _TRUE_VALUES = ('True', 'true', '1', 'yes') class BaseTestCase(testtools.TestCase): def setUp(self): super(BaseTestCase, self).setUp() self._set_timeout() self._fake_output() self.useFixture(fixtures.FakeLogger('keystone.openstack.common')) self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) def _set_timeout(self): test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) def _fake_output(self): if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: stdout = self.useFixture(fixtures.StringStream('stdout')).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: stderr = self.useFixture(fixtures.StringStream('stderr')).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) keystone-2014.1/keystone/openstack/common/fixture/0000775000175400017540000000000012323716511023407 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/fixture/moxstubout.py0000664000175400017540000000230712323716267026224 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2013 Hewlett-Packard Development Company, L.P. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import fixtures import mox class MoxStubout(fixtures.Fixture): """Deal with code around mox and stubout as a fixture.""" def setUp(self): super(MoxStubout, self).setUp() # emulate some of the mox stuff, we can't use the metaclass # because it screws with our generators self.mox = mox.Mox() self.stubs = self.mox.stubs self.addCleanup(self.mox.UnsetStubs) self.addCleanup(self.mox.VerifyAll) keystone-2014.1/keystone/openstack/common/fixture/lockutils.py0000664000175400017540000000354312323716267026007 0ustar jenkinsjenkins00000000000000# Copyright 2011 OpenStack Foundation. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import fixtures from keystone.openstack.common import lockutils class LockFixture(fixtures.Fixture): """External locking fixture. This fixture is basically an alternative to the synchronized decorator with the external flag so that tearDowns and addCleanups will be included in the lock context for locking between tests. The fixture is recommended to be the first line in a test method, like so:: def test_method(self): self.useFixture(LockFixture) ... or the first line in setUp if all the test methods in the class are required to be serialized. Something like:: class TestCase(testtools.testcase): def setUp(self): self.useFixture(LockFixture) super(TestCase, self).setUp() ... This is because addCleanups are put on a LIFO queue that gets run after the test method exits. (either by completing or raising an exception) """ def __init__(self, name, lock_file_prefix=None): self.mgr = lockutils.lock(name, lock_file_prefix, True) def setUp(self): super(LockFixture, self).setUp() self.addCleanup(self.mgr.__exit__, None, None, None) self.mgr.__enter__() keystone-2014.1/keystone/openstack/common/fixture/mockpatch.py0000664000175400017540000000313412323716267025743 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2013 Hewlett-Packard Development Company, L.P. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import fixtures import mock class PatchObject(fixtures.Fixture): """Deal with code around mock.""" def __init__(self, obj, attr, new=mock.DEFAULT, **kwargs): self.obj = obj self.attr = attr self.kwargs = kwargs self.new = new def setUp(self): super(PatchObject, self).setUp() _p = mock.patch.object(self.obj, self.attr, self.new, **self.kwargs) self.mock = _p.start() self.addCleanup(_p.stop) class Patch(fixtures.Fixture): """Deal with code around mock.patch.""" def __init__(self, obj, new=mock.DEFAULT, **kwargs): self.obj = obj self.kwargs = kwargs self.new = new def setUp(self): super(Patch, self).setUp() _p = mock.patch(self.obj, self.new, **self.kwargs) self.mock = _p.start() self.addCleanup(_p.stop) keystone-2014.1/keystone/openstack/common/fixture/config.py0000664000175400017540000000576612323716267025254 0ustar jenkinsjenkins00000000000000# # Copyright 2013 Mirantis, Inc. # Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import fixtures from oslo.config import cfg import six class Config(fixtures.Fixture): """Allows overriding configuration settings for the test. `conf` will be reset on cleanup. """ def __init__(self, conf=cfg.CONF): self.conf = conf def setUp(self): super(Config, self).setUp() # NOTE(morganfainberg): unregister must be added to cleanup before # reset is because cleanup works in reverse order of registered items, # and a reset must occur before unregistering options can occur. self.addCleanup(self._unregister_config_opts) self.addCleanup(self.conf.reset) self._registered_config_opts = {} def config(self, **kw): """Override configuration values. The keyword arguments are the names of configuration options to override and their values. If a `group` argument is supplied, the overrides are applied to the specified configuration option group, otherwise the overrides are applied to the ``default`` group. """ group = kw.pop('group', None) for k, v in six.iteritems(kw): self.conf.set_override(k, v, group) def _unregister_config_opts(self): for group in self._registered_config_opts: self.conf.unregister_opts(self._registered_config_opts[group], group=group) def register_opt(self, opt, group=None): """Register a single option for the test run. Options registered in this manner will automatically be unregistered during cleanup. If a `group` argument is supplied, it will register the new option to that group, otherwise the option is registered to the ``default`` group. """ self.conf.register_opt(opt, group=group) self._registered_config_opts.setdefault(group, set()).add(opt) def register_opts(self, opts, group=None): """Register multiple options for the test run. This works in the same manner as register_opt() but takes a list of options as the first argument. All arguments will be registered to the same group if the ``group`` argument is supplied, otherwise all options will be registered to the ``default`` group. """ for opt in opts: self.register_opt(opt, group=group) keystone-2014.1/keystone/openstack/common/fixture/__init__.py0000664000175400017540000000000012323716267025516 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/db/0000775000175400017540000000000012323716511022306 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/db/options.py0000664000175400017540000001776212323716267024400 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy from oslo.config import cfg database_opts = [ cfg.StrOpt('sqlite_db', deprecated_group='DEFAULT', default='keystone.sqlite', help='The file name to use with SQLite'), cfg.BoolOpt('sqlite_synchronous', deprecated_group='DEFAULT', default=True, help='If True, SQLite uses synchronous mode'), cfg.StrOpt('backend', default='sqlalchemy', deprecated_name='db_backend', deprecated_group='DEFAULT', help='The backend to use for db'), cfg.StrOpt('connection', help='The SQLAlchemy connection string used to connect to the ' 'database', secret=True, deprecated_opts=[cfg.DeprecatedOpt('sql_connection', group='DEFAULT'), cfg.DeprecatedOpt('sql_connection', group='DATABASE'), cfg.DeprecatedOpt('connection', group='sql'), ]), cfg.StrOpt('mysql_sql_mode', default='TRADITIONAL', help='The SQL mode to be used for MySQL sessions. ' 'This option, including the default, overrides any ' 'server-set SQL mode. To use whatever SQL mode ' 'is set by the server configuration, ' 'set this to no value. Example: mysql_sql_mode='), cfg.IntOpt('idle_timeout', default=3600, deprecated_opts=[cfg.DeprecatedOpt('sql_idle_timeout', group='DEFAULT'), cfg.DeprecatedOpt('sql_idle_timeout', group='DATABASE'), cfg.DeprecatedOpt('idle_timeout', group='sql')], help='Timeout before idle sql connections are reaped'), cfg.IntOpt('min_pool_size', default=1, deprecated_opts=[cfg.DeprecatedOpt('sql_min_pool_size', group='DEFAULT'), cfg.DeprecatedOpt('sql_min_pool_size', group='DATABASE')], help='Minimum number of SQL connections to keep open in a ' 'pool'), cfg.IntOpt('max_pool_size', default=None, deprecated_opts=[cfg.DeprecatedOpt('sql_max_pool_size', group='DEFAULT'), cfg.DeprecatedOpt('sql_max_pool_size', group='DATABASE')], help='Maximum number of SQL connections to keep open in a ' 'pool'), cfg.IntOpt('max_retries', default=10, deprecated_opts=[cfg.DeprecatedOpt('sql_max_retries', group='DEFAULT'), cfg.DeprecatedOpt('sql_max_retries', group='DATABASE')], help='Maximum db connection retries during startup. ' '(setting -1 implies an infinite retry count)'), cfg.IntOpt('retry_interval', default=10, deprecated_opts=[cfg.DeprecatedOpt('sql_retry_interval', group='DEFAULT'), cfg.DeprecatedOpt('reconnect_interval', group='DATABASE')], help='Interval between retries of opening a sql connection'), cfg.IntOpt('max_overflow', default=None, deprecated_opts=[cfg.DeprecatedOpt('sql_max_overflow', group='DEFAULT'), cfg.DeprecatedOpt('sqlalchemy_max_overflow', group='DATABASE')], help='If set, use this value for max_overflow with sqlalchemy'), cfg.IntOpt('connection_debug', default=0, deprecated_opts=[cfg.DeprecatedOpt('sql_connection_debug', group='DEFAULT')], help='Verbosity of SQL debugging information. 0=None, ' '100=Everything'), cfg.BoolOpt('connection_trace', default=False, deprecated_opts=[cfg.DeprecatedOpt('sql_connection_trace', group='DEFAULT')], help='Add python stack traces to SQL as comment strings'), cfg.IntOpt('pool_timeout', default=None, deprecated_opts=[cfg.DeprecatedOpt('sqlalchemy_pool_timeout', group='DATABASE')], help='If set, use this value for pool_timeout with sqlalchemy'), cfg.BoolOpt('use_db_reconnect', default=False, help='Enable the experimental use of database reconnect ' 'on connection lost'), cfg.IntOpt('db_retry_interval', default=1, help='seconds between db connection retries'), cfg.BoolOpt('db_inc_retry_interval', default=True, help='Whether to increase interval between db connection ' 'retries, up to db_max_retry_interval'), cfg.IntOpt('db_max_retry_interval', default=10, help='max seconds between db connection retries, if ' 'db_inc_retry_interval is enabled'), cfg.IntOpt('db_max_retries', default=20, help='maximum db connection retries before error is raised. ' '(setting -1 implies an infinite retry count)'), ] CONF = cfg.CONF CONF.register_opts(database_opts, 'database') def set_defaults(sql_connection, sqlite_db, max_pool_size=None, max_overflow=None, pool_timeout=None): """Set defaults for configuration variables.""" cfg.set_defaults(database_opts, connection=sql_connection, sqlite_db=sqlite_db) # Update the QueuePool defaults if max_pool_size is not None: cfg.set_defaults(database_opts, max_pool_size=max_pool_size) if max_overflow is not None: cfg.set_defaults(database_opts, max_overflow=max_overflow) if pool_timeout is not None: cfg.set_defaults(database_opts, pool_timeout=pool_timeout) def list_opts(): """Returns a list of oslo.config options available in the library. The returned list includes all oslo.config options which may be registered at runtime by the library. Each element of the list is a tuple. The first element is the name of the group under which the list of elements in the second element will be registered. A group name of None corresponds to the [DEFAULT] group in config files. The purpose of this is to allow tools like the Oslo sample config file generator to discover the options exposed to users by this library. :returns: a list of (group_name, opts) tuples """ return [('database', copy.deepcopy(database_opts))] keystone-2014.1/keystone/openstack/common/db/sqlalchemy/0000775000175400017540000000000012323716511024450 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/db/sqlalchemy/migration.py0000664000175400017540000002443312323716267027031 0ustar jenkinsjenkins00000000000000# coding: utf-8 # # Copyright (c) 2013 OpenStack Foundation # All Rights Reserved. # # 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. # # Base on code in migrate/changeset/databases/sqlite.py which is under # the following license: # # The MIT License # # Copyright (c) 2009 Evan Rosson, Jan Dittberner, Domen Kožar # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import os import re from migrate.changeset import ansisql from migrate.changeset.databases import sqlite from migrate import exceptions as versioning_exceptions from migrate.versioning import api as versioning_api from migrate.versioning.repository import Repository import sqlalchemy from sqlalchemy.schema import UniqueConstraint from keystone.openstack.common.db import exception from keystone.openstack.common.gettextutils import _ def _get_unique_constraints(self, table): """Retrieve information about existing unique constraints of the table This feature is needed for _recreate_table() to work properly. Unfortunately, it's not available in sqlalchemy 0.7.x/0.8.x. """ data = table.metadata.bind.execute( """SELECT sql FROM sqlite_master WHERE type='table' AND name=:table_name""", table_name=table.name ).fetchone()[0] UNIQUE_PATTERN = "CONSTRAINT (\w+) UNIQUE \(([^\)]+)\)" return [ UniqueConstraint( *[getattr(table.columns, c.strip(' "')) for c in cols.split(",")], name=name ) for name, cols in re.findall(UNIQUE_PATTERN, data) ] def _recreate_table(self, table, column=None, delta=None, omit_uniques=None): """Recreate the table properly Unlike the corresponding original method of sqlalchemy-migrate this one doesn't drop existing unique constraints when creating a new one. """ table_name = self.preparer.format_table(table) # we remove all indexes so as not to have # problems during copy and re-create for index in table.indexes: index.drop() # reflect existing unique constraints for uc in self._get_unique_constraints(table): table.append_constraint(uc) # omit given unique constraints when creating a new table if required table.constraints = set([ cons for cons in table.constraints if omit_uniques is None or cons.name not in omit_uniques ]) self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name) self.execute() insertion_string = self._modify_table(table, column, delta) table.create(bind=self.connection) self.append(insertion_string % {'table_name': table_name}) self.execute() self.append('DROP TABLE migration_tmp') self.execute() def _visit_migrate_unique_constraint(self, *p, **k): """Drop the given unique constraint The corresponding original method of sqlalchemy-migrate just raises NotImplemented error """ self.recreate_table(p[0].table, omit_uniques=[p[0].name]) def patch_migrate(): """A workaround for SQLite's inability to alter things SQLite abilities to alter tables are very limited (please read http://www.sqlite.org/lang_altertable.html for more details). E. g. one can't drop a column or a constraint in SQLite. The workaround for this is to recreate the original table omitting the corresponding constraint (or column). sqlalchemy-migrate library has recreate_table() method that implements this workaround, but it does it wrong: - information about unique constraints of a table is not retrieved. So if you have a table with one unique constraint and a migration adding another one you will end up with a table that has only the latter unique constraint, and the former will be lost - dropping of unique constraints is not supported at all The proper way to fix this is to provide a pull-request to sqlalchemy-migrate, but the project seems to be dead. So we can go on with monkey-patching of the lib at least for now. """ # this patch is needed to ensure that recreate_table() doesn't drop # existing unique constraints of the table when creating a new one helper_cls = sqlite.SQLiteHelper helper_cls.recreate_table = _recreate_table helper_cls._get_unique_constraints = _get_unique_constraints # this patch is needed to be able to drop existing unique constraints constraint_cls = sqlite.SQLiteConstraintDropper constraint_cls.visit_migrate_unique_constraint = \ _visit_migrate_unique_constraint constraint_cls.__bases__ = (ansisql.ANSIColumnDropper, sqlite.SQLiteConstraintGenerator) def db_sync(engine, abs_path, version=None, init_version=0, sanity_check=True): """Upgrade or downgrade a database. Function runs the upgrade() or downgrade() functions in change scripts. :param engine: SQLAlchemy engine instance for a given database :param abs_path: Absolute path to migrate repository. :param version: Database will upgrade/downgrade until this version. If None - database will update to the latest available version. :param init_version: Initial database version :param sanity_check: Require schema sanity checking for all tables """ if version is not None: try: version = int(version) except ValueError: raise exception.DbMigrationError( message=_("version should be an integer")) current_version = db_version(engine, abs_path, init_version) repository = _find_migrate_repo(abs_path) if sanity_check: _db_schema_sanity_check(engine) if version is None or version > current_version: return versioning_api.upgrade(engine, repository, version) else: return versioning_api.downgrade(engine, repository, version) def _db_schema_sanity_check(engine): """Ensure all database tables were created with required parameters. :param engine: SQLAlchemy engine instance for a given database """ if engine.name == 'mysql': onlyutf8_sql = ('SELECT TABLE_NAME,TABLE_COLLATION ' 'from information_schema.TABLES ' 'where TABLE_SCHEMA=%s and ' 'TABLE_COLLATION NOT LIKE "%%utf8%%"') # NOTE(morganfainberg): exclude the sqlalchemy-migrate and alembic # versioning tables from the tables we need to verify utf8 status on. # Non-standard table names are not supported. EXCLUDED_TABLES = ['migrate_version', 'alembic_version'] table_names = [res[0] for res in engine.execute(onlyutf8_sql, engine.url.database) if res[0].lower() not in EXCLUDED_TABLES] if len(table_names) > 0: raise ValueError(_('Tables "%s" have non utf8 collation, ' 'please make sure all tables are CHARSET=utf8' ) % ','.join(table_names)) def db_version(engine, abs_path, init_version): """Show the current version of the repository. :param engine: SQLAlchemy engine instance for a given database :param abs_path: Absolute path to migrate repository :param version: Initial database version """ repository = _find_migrate_repo(abs_path) try: return versioning_api.db_version(engine, repository) except versioning_exceptions.DatabaseNotControlledError: meta = sqlalchemy.MetaData() meta.reflect(bind=engine) tables = meta.tables if len(tables) == 0 or 'alembic_version' in tables: db_version_control(engine, abs_path, version=init_version) return versioning_api.db_version(engine, repository) else: raise exception.DbMigrationError( message=_( "The database is not under version control, but has " "tables. Please stamp the current version of the schema " "manually.")) def db_version_control(engine, abs_path, version=None): """Mark a database as under this repository's version control. Once a database is under version control, schema changes should only be done via change scripts in this repository. :param engine: SQLAlchemy engine instance for a given database :param abs_path: Absolute path to migrate repository :param version: Initial database version """ repository = _find_migrate_repo(abs_path) versioning_api.version_control(engine, repository, version) return version def _find_migrate_repo(abs_path): """Get the project's change script repository :param abs_path: Absolute path to migrate repository """ if not os.path.exists(abs_path): raise exception.DbMigrationError("Path %s not found" % abs_path) return Repository(abs_path) keystone-2014.1/keystone/openstack/common/db/sqlalchemy/session.py0000664000175400017540000010452712323716267026526 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """Session Handling for SQLAlchemy backend. Recommended ways to use sessions within this framework: * Don't use them explicitly; this is like running with ``AUTOCOMMIT=1``. `model_query()` will implicitly use a session when called without one supplied. This is the ideal situation because it will allow queries to be automatically retried if the database connection is interrupted. .. note:: Automatic retry will be enabled in a future patch. It is generally fine to issue several queries in a row like this. Even though they may be run in separate transactions and/or separate sessions, each one will see the data from the prior calls. If needed, undo- or rollback-like functionality should be handled at a logical level. For an example, look at the code around quotas and `reservation_rollback()`. Examples: .. code:: python def get_foo(context, foo): return (model_query(context, models.Foo). filter_by(foo=foo). first()) def update_foo(context, id, newfoo): (model_query(context, models.Foo). filter_by(id=id). update({'foo': newfoo})) def create_foo(context, values): foo_ref = models.Foo() foo_ref.update(values) foo_ref.save() return foo_ref * Within the scope of a single method, keep all the reads and writes within the context managed by a single session. In this way, the session's `__exit__` handler will take care of calling `flush()` and `commit()` for you. If using this approach, you should not explicitly call `flush()` or `commit()`. Any error within the context of the session will cause the session to emit a `ROLLBACK`. Database errors like `IntegrityError` will be raised in `session`'s `__exit__` handler, and any try/except within the context managed by `session` will not be triggered. And catching other non-database errors in the session will not trigger the ROLLBACK, so exception handlers should always be outside the session, unless the developer wants to do a partial commit on purpose. If the connection is dropped before this is possible, the database will implicitly roll back the transaction. .. note:: Statements in the session scope will not be automatically retried. If you create models within the session, they need to be added, but you do not need to call `model.save()`: .. code:: python def create_many_foo(context, foos): session = sessionmaker() with session.begin(): for foo in foos: foo_ref = models.Foo() foo_ref.update(foo) session.add(foo_ref) def update_bar(context, foo_id, newbar): session = sessionmaker() with session.begin(): foo_ref = (model_query(context, models.Foo, session). filter_by(id=foo_id). first()) (model_query(context, models.Bar, session). filter_by(id=foo_ref['bar_id']). update({'bar': newbar})) .. note:: `update_bar` is a trivially simple example of using ``with session.begin``. Whereas `create_many_foo` is a good example of when a transaction is needed, it is always best to use as few queries as possible. The two queries in `update_bar` can be better expressed using a single query which avoids the need for an explicit transaction. It can be expressed like so: .. code:: python def update_bar(context, foo_id, newbar): subq = (model_query(context, models.Foo.id). filter_by(id=foo_id). limit(1). subquery()) (model_query(context, models.Bar). filter_by(id=subq.as_scalar()). update({'bar': newbar})) For reference, this emits approximately the following SQL statement: .. code:: sql UPDATE bar SET bar = ${newbar} WHERE id=(SELECT bar_id FROM foo WHERE id = ${foo_id} LIMIT 1); .. note:: `create_duplicate_foo` is a trivially simple example of catching an exception while using ``with session.begin``. Here create two duplicate instances with same primary key, must catch the exception out of context managed by a single session: .. code:: python def create_duplicate_foo(context): foo1 = models.Foo() foo2 = models.Foo() foo1.id = foo2.id = 1 session = sessionmaker() try: with session.begin(): session.add(foo1) session.add(foo2) except exception.DBDuplicateEntry as e: handle_error(e) * Passing an active session between methods. Sessions should only be passed to private methods. The private method must use a subtransaction; otherwise SQLAlchemy will throw an error when you call `session.begin()` on an existing transaction. Public methods should not accept a session parameter and should not be involved in sessions within the caller's scope. Note that this incurs more overhead in SQLAlchemy than the above means due to nesting transactions, and it is not possible to implicitly retry failed database operations when using this approach. This also makes code somewhat more difficult to read and debug, because a single database transaction spans more than one method. Error handling becomes less clear in this situation. When this is needed for code clarity, it should be clearly documented. .. code:: python def myfunc(foo): session = sessionmaker() with session.begin(): # do some database things bar = _private_func(foo, session) return bar def _private_func(foo, session=None): if not session: session = sessionmaker() with session.begin(subtransaction=True): # do some other database things return bar There are some things which it is best to avoid: * Don't keep a transaction open any longer than necessary. This means that your ``with session.begin()`` block should be as short as possible, while still containing all the related calls for that transaction. * Avoid ``with_lockmode('UPDATE')`` when possible. In MySQL/InnoDB, when a ``SELECT ... FOR UPDATE`` query does not match any rows, it will take a gap-lock. This is a form of write-lock on the "gap" where no rows exist, and prevents any other writes to that space. This can effectively prevent any INSERT into a table by locking the gap at the end of the index. Similar problems will occur if the SELECT FOR UPDATE has an overly broad WHERE clause, or doesn't properly use an index. One idea proposed at ODS Fall '12 was to use a normal SELECT to test the number of rows matching a query, and if only one row is returned, then issue the SELECT FOR UPDATE. The better long-term solution is to use ``INSERT .. ON DUPLICATE KEY UPDATE``. However, this can not be done until the "deleted" columns are removed and proper UNIQUE constraints are added to the tables. Enabling soft deletes: * To use/enable soft-deletes, the `SoftDeleteMixin` must be added to your model class. For example: .. code:: python class NovaBase(models.SoftDeleteMixin, models.ModelBase): pass Efficient use of soft deletes: * There are two possible ways to mark a record as deleted: `model.soft_delete()` and `query.soft_delete()`. The `model.soft_delete()` method works with a single already-fetched entry. `query.soft_delete()` makes only one db request for all entries that correspond to the query. * In almost all cases you should use `query.soft_delete()`. Some examples: .. code:: python def soft_delete_bar(): count = model_query(BarModel).find(some_condition).soft_delete() if count == 0: raise Exception("0 entries were soft deleted") def complex_soft_delete_with_synchronization_bar(session=None): if session is None: session = sessionmaker() with session.begin(subtransactions=True): count = (model_query(BarModel). find(some_condition). soft_delete(synchronize_session=True)) # Here synchronize_session is required, because we # don't know what is going on in outer session. if count == 0: raise Exception("0 entries were soft deleted") * There is only one situation where `model.soft_delete()` is appropriate: when you fetch a single record, work with it, and mark it as deleted in the same transaction. .. code:: python def soft_delete_bar_model(): session = sessionmaker() with session.begin(): bar_ref = model_query(BarModel).find(some_condition).first() # Work with bar_ref bar_ref.soft_delete(session=session) However, if you need to work with all entries that correspond to query and then soft delete them you should use the `query.soft_delete()` method: .. code:: python def soft_delete_multi_models(): session = sessionmaker() with session.begin(): query = (model_query(BarModel, session=session). find(some_condition)) model_refs = query.all() # Work with model_refs query.soft_delete(synchronize_session=False) # synchronize_session=False should be set if there is no outer # session and these entries are not used after this. When working with many rows, it is very important to use query.soft_delete, which issues a single query. Using `model.soft_delete()`, as in the following example, is very inefficient. .. code:: python for bar_ref in bar_refs: bar_ref.soft_delete(session=session) # This will produce count(bar_refs) db requests. """ import functools import logging import re import time import six from sqlalchemy import exc as sqla_exc from sqlalchemy.interfaces import PoolListener import sqlalchemy.orm from sqlalchemy.pool import NullPool, StaticPool from sqlalchemy.sql.expression import literal_column from keystone.openstack.common.db import exception from keystone.openstack.common.gettextutils import _LE, _LW from keystone.openstack.common import timeutils LOG = logging.getLogger(__name__) class SqliteForeignKeysListener(PoolListener): """Ensures that the foreign key constraints are enforced in SQLite. The foreign key constraints are disabled by default in SQLite, so the foreign key constraints will be enabled here for every database connection """ def connect(self, dbapi_con, con_record): dbapi_con.execute('pragma foreign_keys=ON') # note(boris-42): In current versions of DB backends unique constraint # violation messages follow the structure: # # sqlite: # 1 column - (IntegrityError) column c1 is not unique # N columns - (IntegrityError) column c1, c2, ..., N are not unique # # sqlite since 3.7.16: # 1 column - (IntegrityError) UNIQUE constraint failed: tbl.k1 # # N columns - (IntegrityError) UNIQUE constraint failed: tbl.k1, tbl.k2 # # postgres: # 1 column - (IntegrityError) duplicate key value violates unique # constraint "users_c1_key" # N columns - (IntegrityError) duplicate key value violates unique # constraint "name_of_our_constraint" # # mysql: # 1 column - (IntegrityError) (1062, "Duplicate entry 'value_of_c1' for key # 'c1'") # N columns - (IntegrityError) (1062, "Duplicate entry 'values joined # with -' for key 'name_of_our_constraint'") # # ibm_db_sa: # N columns - (IntegrityError) SQL0803N One or more values in the INSERT # statement, UPDATE statement, or foreign key update caused by a # DELETE statement are not valid because the primary key, unique # constraint or unique index identified by "2" constrains table # "NOVA.KEY_PAIRS" from having duplicate values for the index # key. _DUP_KEY_RE_DB = { "sqlite": (re.compile(r"^.*columns?([^)]+)(is|are)\s+not\s+unique$"), re.compile(r"^.*UNIQUE\s+constraint\s+failed:\s+(.+)$")), "postgresql": (re.compile(r"^.*duplicate\s+key.*\"([^\"]+)\"\s*\n.*$"),), "mysql": (re.compile(r"^.*\(1062,.*'([^\']+)'\"\)$"),), "ibm_db_sa": (re.compile(r"^.*SQL0803N.*$"),), } def _raise_if_duplicate_entry_error(integrity_error, engine_name): """Raise exception if two entries are duplicated. In this function will be raised DBDuplicateEntry exception if integrity error wrap unique constraint violation. """ def get_columns_from_uniq_cons_or_name(columns): # note(vsergeyev): UniqueConstraint name convention: "uniq_t0c10c2" # where `t` it is table name and columns `c1`, `c2` # are in UniqueConstraint. uniqbase = "uniq_" if not columns.startswith(uniqbase): if engine_name == "postgresql": return [columns[columns.index("_") + 1:columns.rindex("_")]] return [columns] return columns[len(uniqbase):].split("0")[1:] if engine_name not in ["ibm_db_sa", "mysql", "sqlite", "postgresql"]: return # FIXME(johannes): The usage of the .message attribute has been # deprecated since Python 2.6. However, the exceptions raised by # SQLAlchemy can differ when using unicode() and accessing .message. # An audit across all three supported engines will be necessary to # ensure there are no regressions. for pattern in _DUP_KEY_RE_DB[engine_name]: match = pattern.match(integrity_error.message) if match: break else: return # NOTE(mriedem): The ibm_db_sa integrity error message doesn't provide the # columns so we have to omit that from the DBDuplicateEntry error. columns = '' if engine_name != 'ibm_db_sa': columns = match.group(1) if engine_name == "sqlite": columns = [c.split('.')[-1] for c in columns.strip().split(", ")] else: columns = get_columns_from_uniq_cons_or_name(columns) raise exception.DBDuplicateEntry(columns, integrity_error) # NOTE(comstud): In current versions of DB backends, Deadlock violation # messages follow the structure: # # mysql: # (OperationalError) (1213, 'Deadlock found when trying to get lock; try ' # 'restarting transaction') _DEADLOCK_RE_DB = { "mysql": re.compile(r"^.*\(1213, 'Deadlock.*") } def _raise_if_deadlock_error(operational_error, engine_name): """Raise exception on deadlock condition. Raise DBDeadlock exception if OperationalError contains a Deadlock condition. """ re = _DEADLOCK_RE_DB.get(engine_name) if re is None: return # FIXME(johannes): The usage of the .message attribute has been # deprecated since Python 2.6. However, the exceptions raised by # SQLAlchemy can differ when using unicode() and accessing .message. # An audit across all three supported engines will be necessary to # ensure there are no regressions. m = re.match(operational_error.message) if not m: return raise exception.DBDeadlock(operational_error) def _wrap_db_error(f): @functools.wraps(f) def _wrap(self, *args, **kwargs): try: assert issubclass( self.__class__, sqlalchemy.orm.session.Session ), ('_wrap_db_error() can only be applied to methods of ' 'subclasses of sqlalchemy.orm.session.Session.') return f(self, *args, **kwargs) except UnicodeEncodeError: raise exception.DBInvalidUnicodeParameter() except sqla_exc.OperationalError as e: _raise_if_db_connection_lost(e, self.bind) _raise_if_deadlock_error(e, self.bind.dialect.name) # NOTE(comstud): A lot of code is checking for OperationalError # so let's not wrap it for now. raise # note(boris-42): We should catch unique constraint violation and # wrap it by our own DBDuplicateEntry exception. Unique constraint # violation is wrapped by IntegrityError. except sqla_exc.IntegrityError as e: # note(boris-42): SqlAlchemy doesn't unify errors from different # DBs so we must do this. Also in some tables (for example # instance_types) there are more than one unique constraint. This # means we should get names of columns, which values violate # unique constraint, from error message. _raise_if_duplicate_entry_error(e, self.bind.dialect.name) raise exception.DBError(e) except Exception as e: LOG.exception(_LE('DB exception wrapped.')) raise exception.DBError(e) return _wrap def _synchronous_switch_listener(dbapi_conn, connection_rec): """Switch sqlite connections to non-synchronous mode.""" dbapi_conn.execute("PRAGMA synchronous = OFF") def _add_regexp_listener(dbapi_con, con_record): """Add REGEXP function to sqlite connections.""" def regexp(expr, item): reg = re.compile(expr) return reg.search(six.text_type(item)) is not None dbapi_con.create_function('regexp', 2, regexp) def _thread_yield(dbapi_con, con_record): """Ensure other greenthreads get a chance to be executed. If we use eventlet.monkey_patch(), eventlet.greenthread.sleep(0) will execute instead of time.sleep(0). Force a context switch. With common database backends (eg MySQLdb and sqlite), there is no implicit yield caused by network I/O since they are implemented by C libraries that eventlet cannot monkey patch. """ time.sleep(0) def _ping_listener(engine, dbapi_conn, connection_rec, connection_proxy): """Ensures that MySQL and DB2 connections are alive. Borrowed from: http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f """ cursor = dbapi_conn.cursor() try: ping_sql = 'select 1' if engine.name == 'ibm_db_sa': # DB2 requires a table expression ping_sql = 'select 1 from (values (1)) AS t1' cursor.execute(ping_sql) except Exception as ex: if engine.dialect.is_disconnect(ex, dbapi_conn, cursor): msg = _LW('Database server has gone away: %s') % ex LOG.warning(msg) # if the database server has gone away, all connections in the pool # have become invalid and we can safely close all of them here, # rather than waste time on checking of every single connection engine.dispose() # this will be handled by SQLAlchemy and will force it to create # a new connection and retry the original action raise sqla_exc.DisconnectionError(msg) else: raise def _set_session_sql_mode(dbapi_con, connection_rec, sql_mode=None): """Set the sql_mode session variable. MySQL supports several server modes. The default is None, but sessions may choose to enable server modes like TRADITIONAL, ANSI, several STRICT_* modes and others. Note: passing in '' (empty string) for sql_mode clears the SQL mode for the session, overriding a potentially set server default. """ cursor = dbapi_con.cursor() cursor.execute("SET SESSION sql_mode = %s", [sql_mode]) def _mysql_get_effective_sql_mode(engine): """Returns the effective SQL mode for connections from the engine pool. Returns ``None`` if the mode isn't available, otherwise returns the mode. """ # Get the real effective SQL mode. Even when unset by # our own config, the server may still be operating in a specific # SQL mode as set by the server configuration. # Also note that the checkout listener will be called on execute to # set the mode if it's registered. row = engine.execute("SHOW VARIABLES LIKE 'sql_mode'").fetchone() if row is None: return return row[1] def _mysql_check_effective_sql_mode(engine): """Logs a message based on the effective SQL mode for MySQL connections.""" realmode = _mysql_get_effective_sql_mode(engine) if realmode is None: LOG.warning(_LW('Unable to detect effective SQL mode')) return LOG.debug('MySQL server mode set to %s', realmode) # 'TRADITIONAL' mode enables several other modes, so # we need a substring match here if not ('TRADITIONAL' in realmode.upper() or 'STRICT_ALL_TABLES' in realmode.upper()): LOG.warning(_LW("MySQL SQL mode is '%s', " "consider enabling TRADITIONAL or STRICT_ALL_TABLES"), realmode) def _mysql_set_mode_callback(engine, sql_mode): if sql_mode is not None: mode_callback = functools.partial(_set_session_sql_mode, sql_mode=sql_mode) sqlalchemy.event.listen(engine, 'connect', mode_callback) _mysql_check_effective_sql_mode(engine) def _is_db_connection_error(args): """Return True if error in connecting to db.""" # NOTE(adam_g): This is currently MySQL specific and needs to be extended # to support Postgres and others. # For the db2, the error code is -30081 since the db2 is still not ready conn_err_codes = ('2002', '2003', '2006', '2013', '-30081') for err_code in conn_err_codes: if args.find(err_code) != -1: return True return False def _raise_if_db_connection_lost(error, engine): # NOTE(vsergeyev): Function is_disconnect(e, connection, cursor) # requires connection and cursor in incoming parameters, # but we have no possibility to create connection if DB # is not available, so in such case reconnect fails. # But is_disconnect() ignores these parameters, so it # makes sense to pass to function None as placeholder # instead of connection and cursor. if engine.dialect.is_disconnect(error, None, None): raise exception.DBConnectionError(error) def create_engine(sql_connection, sqlite_fk=False, mysql_sql_mode=None, idle_timeout=3600, connection_debug=0, max_pool_size=None, max_overflow=None, pool_timeout=None, sqlite_synchronous=True, connection_trace=False, max_retries=10, retry_interval=10): """Return a new SQLAlchemy engine.""" connection_dict = sqlalchemy.engine.url.make_url(sql_connection) engine_args = { "pool_recycle": idle_timeout, 'convert_unicode': True, } logger = logging.getLogger('sqlalchemy.engine') # Map SQL debug level to Python log level if connection_debug >= 100: logger.setLevel(logging.DEBUG) elif connection_debug >= 50: logger.setLevel(logging.INFO) else: logger.setLevel(logging.WARNING) if "sqlite" in connection_dict.drivername: if sqlite_fk: engine_args["listeners"] = [SqliteForeignKeysListener()] engine_args["poolclass"] = NullPool if sql_connection == "sqlite://": engine_args["poolclass"] = StaticPool engine_args["connect_args"] = {'check_same_thread': False} else: if max_pool_size is not None: engine_args['pool_size'] = max_pool_size if max_overflow is not None: engine_args['max_overflow'] = max_overflow if pool_timeout is not None: engine_args['pool_timeout'] = pool_timeout engine = sqlalchemy.create_engine(sql_connection, **engine_args) sqlalchemy.event.listen(engine, 'checkin', _thread_yield) if engine.name in ['mysql', 'ibm_db_sa']: ping_callback = functools.partial(_ping_listener, engine) sqlalchemy.event.listen(engine, 'checkout', ping_callback) if engine.name == 'mysql': if mysql_sql_mode: _mysql_set_mode_callback(engine, mysql_sql_mode) elif 'sqlite' in connection_dict.drivername: if not sqlite_synchronous: sqlalchemy.event.listen(engine, 'connect', _synchronous_switch_listener) sqlalchemy.event.listen(engine, 'connect', _add_regexp_listener) if connection_trace and engine.dialect.dbapi.__name__ == 'MySQLdb': _patch_mysqldb_with_stacktrace_comments() try: engine.connect() except sqla_exc.OperationalError as e: if not _is_db_connection_error(e.args[0]): raise remaining = max_retries if remaining == -1: remaining = 'infinite' while True: msg = _LW('SQL connection failed. %s attempts left.') LOG.warning(msg % remaining) if remaining != 'infinite': remaining -= 1 time.sleep(retry_interval) try: engine.connect() break except sqla_exc.OperationalError as e: if (remaining != 'infinite' and remaining == 0) or \ not _is_db_connection_error(e.args[0]): raise return engine class Query(sqlalchemy.orm.query.Query): """Subclass of sqlalchemy.query with soft_delete() method.""" def soft_delete(self, synchronize_session='evaluate'): return self.update({'deleted': literal_column('id'), 'updated_at': literal_column('updated_at'), 'deleted_at': timeutils.utcnow()}, synchronize_session=synchronize_session) class Session(sqlalchemy.orm.session.Session): """Custom Session class to avoid SqlAlchemy Session monkey patching.""" @_wrap_db_error def query(self, *args, **kwargs): return super(Session, self).query(*args, **kwargs) @_wrap_db_error def flush(self, *args, **kwargs): return super(Session, self).flush(*args, **kwargs) @_wrap_db_error def execute(self, *args, **kwargs): return super(Session, self).execute(*args, **kwargs) def get_maker(engine, autocommit=True, expire_on_commit=False): """Return a SQLAlchemy sessionmaker using the given engine.""" return sqlalchemy.orm.sessionmaker(bind=engine, class_=Session, autocommit=autocommit, expire_on_commit=expire_on_commit, query_cls=Query) def _patch_mysqldb_with_stacktrace_comments(): """Adds current stack trace as a comment in queries. Patches MySQLdb.cursors.BaseCursor._do_query. """ import MySQLdb.cursors import traceback old_mysql_do_query = MySQLdb.cursors.BaseCursor._do_query def _do_query(self, q): stack = '' for filename, line, method, function in traceback.extract_stack(): # exclude various common things from trace if filename.endswith('session.py') and method == '_do_query': continue if filename.endswith('api.py') and method == 'wrapper': continue if filename.endswith('utils.py') and method == '_inner': continue if filename.endswith('exception.py') and method == '_wrap': continue # db/api is just a wrapper around db/sqlalchemy/api if filename.endswith('db/api.py'): continue # only trace inside keystone index = filename.rfind('keystone') if index == -1: continue stack += "File:%s:%s Method:%s() Line:%s | " \ % (filename[index:], line, method, function) # strip trailing " | " from stack if stack: stack = stack[:-3] qq = "%s /* %s */" % (q, stack) else: qq = q old_mysql_do_query(self, qq) setattr(MySQLdb.cursors.BaseCursor, '_do_query', _do_query) class EngineFacade(object): """A helper class for removing of global engine instances from keystone.db. As a library, keystone.db can't decide where to store/when to create engine and sessionmaker instances, so this must be left for a target application. On the other hand, in order to simplify the adoption of keystone.db changes, we'll provide a helper class, which creates engine and sessionmaker on its instantiation and provides get_engine()/get_session() methods that are compatible with corresponding utility functions that currently exist in target projects, e.g. in Nova. engine/sessionmaker instances will still be global (and they are meant to be global), but they will be stored in the app context, rather that in the keystone.db context. Note: using of this helper is completely optional and you are encouraged to integrate engine/sessionmaker instances into your apps any way you like (e.g. one might want to bind a session to a request context). Two important things to remember: 1. An Engine instance is effectively a pool of DB connections, so it's meant to be shared (and it's thread-safe). 2. A Session instance is not meant to be shared and represents a DB transactional context (i.e. it's not thread-safe). sessionmaker is a factory of sessions. """ def __init__(self, sql_connection, sqlite_fk=False, autocommit=True, expire_on_commit=False, **kwargs): """Initialize engine and sessionmaker instances. :param sqlite_fk: enable foreign keys in SQLite :type sqlite_fk: bool :param autocommit: use autocommit mode for created Session instances :type autocommit: bool :param expire_on_commit: expire session objects on commit :type expire_on_commit: bool Keyword arguments: :keyword mysql_sql_mode: the SQL mode to be used for MySQL sessions. (defaults to TRADITIONAL) :keyword idle_timeout: timeout before idle sql connections are reaped (defaults to 3600) :keyword connection_debug: verbosity of SQL debugging information. 0=None, 100=Everything (defaults to 0) :keyword max_pool_size: maximum number of SQL connections to keep open in a pool (defaults to SQLAlchemy settings) :keyword max_overflow: if set, use this value for max_overflow with sqlalchemy (defaults to SQLAlchemy settings) :keyword pool_timeout: if set, use this value for pool_timeout with sqlalchemy (defaults to SQLAlchemy settings) :keyword sqlite_synchronous: if True, SQLite uses synchronous mode (defaults to True) :keyword connection_trace: add python stack traces to SQL as comment strings (defaults to False) :keyword max_retries: maximum db connection retries during startup. (setting -1 implies an infinite retry count) (defaults to 10) :keyword retry_interval: interval between retries of opening a sql connection (defaults to 10) """ super(EngineFacade, self).__init__() self._engine = create_engine( sql_connection=sql_connection, sqlite_fk=sqlite_fk, mysql_sql_mode=kwargs.get('mysql_sql_mode', 'TRADITIONAL'), idle_timeout=kwargs.get('idle_timeout', 3600), connection_debug=kwargs.get('connection_debug', 0), max_pool_size=kwargs.get('max_pool_size'), max_overflow=kwargs.get('max_overflow'), pool_timeout=kwargs.get('pool_timeout'), sqlite_synchronous=kwargs.get('sqlite_synchronous', True), connection_trace=kwargs.get('connection_trace', False), max_retries=kwargs.get('max_retries', 10), retry_interval=kwargs.get('retry_interval', 10)) self._session_maker = get_maker( engine=self._engine, autocommit=autocommit, expire_on_commit=expire_on_commit) def get_engine(self): """Get the engine instance (note, that it's shared).""" return self._engine def get_session(self, **kwargs): """Get a Session instance. If passed, keyword arguments values override the ones used when the sessionmaker instance was created. :keyword autocommit: use autocommit mode for created Session instances :type autocommit: bool :keyword expire_on_commit: expire session objects on commit :type expire_on_commit: bool """ for arg in kwargs: if arg not in ('autocommit', 'expire_on_commit'): del kwargs[arg] return self._session_maker(**kwargs) @classmethod def from_config(cls, connection_string, conf, sqlite_fk=False, autocommit=True, expire_on_commit=False): """Initialize EngineFacade using oslo.config config instance options. :param connection_string: SQLAlchemy connection string :type connection_string: string :param conf: oslo.config config instance :type conf: oslo.config.cfg.ConfigOpts :param sqlite_fk: enable foreign keys in SQLite :type sqlite_fk: bool :param autocommit: use autocommit mode for created Session instances :type autocommit: bool :param expire_on_commit: expire session objects on commit :type expire_on_commit: bool """ return cls(sql_connection=connection_string, sqlite_fk=sqlite_fk, autocommit=autocommit, expire_on_commit=expire_on_commit, **dict(conf.database.items())) keystone-2014.1/keystone/openstack/common/db/sqlalchemy/utils.py0000664000175400017540000005734612323716267026211 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2010-2011 OpenStack Foundation. # Copyright 2012 Justin Santa Barbara # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging import re import sqlalchemy from sqlalchemy import Boolean from sqlalchemy import CheckConstraint from sqlalchemy import Column from sqlalchemy.engine import reflection from sqlalchemy.ext.compiler import compiles from sqlalchemy import func from sqlalchemy import Index from sqlalchemy import Integer from sqlalchemy import MetaData from sqlalchemy import or_ from sqlalchemy.sql.expression import literal_column from sqlalchemy.sql.expression import UpdateBase from sqlalchemy import String from sqlalchemy import Table from sqlalchemy.types import NullType from keystone.openstack.common import context as request_context from keystone.openstack.common.db.sqlalchemy import models from keystone.openstack.common.gettextutils import _, _LI, _LW from keystone.openstack.common import timeutils LOG = logging.getLogger(__name__) _DBURL_REGEX = re.compile(r"[^:]+://([^:]+):([^@]+)@.+") def sanitize_db_url(url): match = _DBURL_REGEX.match(url) if match: return '%s****:****%s' % (url[:match.start(1)], url[match.end(2):]) return url class InvalidSortKey(Exception): message = _("Sort key supplied was not valid.") # copy from glance/db/sqlalchemy/api.py def paginate_query(query, model, limit, sort_keys, marker=None, sort_dir=None, sort_dirs=None): """Returns a query with sorting / pagination criteria added. Pagination works by requiring a unique sort_key, specified by sort_keys. (If sort_keys is not unique, then we risk looping through values.) We use the last row in the previous page as the 'marker' for pagination. So we must return values that follow the passed marker in the order. With a single-valued sort_key, this would be easy: sort_key > X. With a compound-values sort_key, (k1, k2, k3) we must do this to repeat the lexicographical ordering: (k1 > X1) or (k1 == X1 && k2 > X2) or (k1 == X1 && k2 == X2 && k3 > X3) We also have to cope with different sort_directions. Typically, the id of the last row is used as the client-facing pagination marker, then the actual marker object must be fetched from the db and passed in to us as marker. :param query: the query object to which we should add paging/sorting :param model: the ORM model class :param limit: maximum number of items to return :param sort_keys: array of attributes by which results should be sorted :param marker: the last item of the previous page; we returns the next results after this value. :param sort_dir: direction in which results should be sorted (asc, desc) :param sort_dirs: per-column array of sort_dirs, corresponding to sort_keys :rtype: sqlalchemy.orm.query.Query :return: The query with sorting/pagination added. """ if 'id' not in sort_keys: # TODO(justinsb): If this ever gives a false-positive, check # the actual primary key, rather than assuming its id LOG.warning(_LW('Id not in sort_keys; is sort_keys unique?')) assert(not (sort_dir and sort_dirs)) # Default the sort direction to ascending if sort_dirs is None and sort_dir is None: sort_dir = 'asc' # Ensure a per-column sort direction if sort_dirs is None: sort_dirs = [sort_dir for _sort_key in sort_keys] assert(len(sort_dirs) == len(sort_keys)) # Add sorting for current_sort_key, current_sort_dir in zip(sort_keys, sort_dirs): try: sort_dir_func = { 'asc': sqlalchemy.asc, 'desc': sqlalchemy.desc, }[current_sort_dir] except KeyError: raise ValueError(_("Unknown sort direction, " "must be 'desc' or 'asc'")) try: sort_key_attr = getattr(model, current_sort_key) except AttributeError: raise InvalidSortKey() query = query.order_by(sort_dir_func(sort_key_attr)) # Add pagination if marker is not None: marker_values = [] for sort_key in sort_keys: v = getattr(marker, sort_key) marker_values.append(v) # Build up an array of sort criteria as in the docstring criteria_list = [] for i in range(len(sort_keys)): crit_attrs = [] for j in range(i): model_attr = getattr(model, sort_keys[j]) crit_attrs.append((model_attr == marker_values[j])) model_attr = getattr(model, sort_keys[i]) if sort_dirs[i] == 'desc': crit_attrs.append((model_attr < marker_values[i])) else: crit_attrs.append((model_attr > marker_values[i])) criteria = sqlalchemy.sql.and_(*crit_attrs) criteria_list.append(criteria) f = sqlalchemy.sql.or_(*criteria_list) query = query.filter(f) if limit is not None: query = query.limit(limit) return query def _read_deleted_filter(query, db_model, read_deleted): if 'deleted' not in db_model.__table__.columns: raise ValueError(_("There is no `deleted` column in `%s` table. " "Project doesn't use soft-deleted feature.") % db_model.__name__) default_deleted_value = db_model.__table__.c.deleted.default.arg if read_deleted == 'no': query = query.filter(db_model.deleted == default_deleted_value) elif read_deleted == 'yes': pass # omit the filter to include deleted and active elif read_deleted == 'only': query = query.filter(db_model.deleted != default_deleted_value) else: raise ValueError(_("Unrecognized read_deleted value '%s'") % read_deleted) return query def _project_filter(query, db_model, context, project_only): if project_only and 'project_id' not in db_model.__table__.columns: raise ValueError(_("There is no `project_id` column in `%s` table.") % db_model.__name__) if request_context.is_user_context(context) and project_only: if project_only == 'allow_none': is_none = None query = query.filter(or_(db_model.project_id == context.project_id, db_model.project_id == is_none)) else: query = query.filter(db_model.project_id == context.project_id) return query def model_query(context, model, session, args=None, project_only=False, read_deleted=None): """Query helper that accounts for context's `read_deleted` field. :param context: context to query under :param model: Model to query. Must be a subclass of ModelBase. :type model: models.ModelBase :param session: The session to use. :type session: sqlalchemy.orm.session.Session :param args: Arguments to query. If None - model is used. :type args: tuple :param project_only: If present and context is user-type, then restrict query to match the context's project_id. If set to 'allow_none', restriction includes project_id = None. :type project_only: bool :param read_deleted: If present, overrides context's read_deleted field. :type read_deleted: bool Usage: ..code:: python result = (utils.model_query(context, models.Instance, session=session) .filter_by(uuid=instance_uuid) .all()) query = utils.model_query( context, Node, session=session, args=(func.count(Node.id), func.sum(Node.ram)) ).filter_by(project_id=project_id) """ if not read_deleted: if hasattr(context, 'read_deleted'): # NOTE(viktors): some projects use `read_deleted` attribute in # their contexts instead of `show_deleted`. read_deleted = context.read_deleted else: read_deleted = context.show_deleted if not issubclass(model, models.ModelBase): raise TypeError(_("model should be a subclass of ModelBase")) query = session.query(model) if not args else session.query(*args) query = _read_deleted_filter(query, model, read_deleted) query = _project_filter(query, model, context, project_only) return query def get_table(engine, name): """Returns an sqlalchemy table dynamically from db. Needed because the models don't work for us in migrations as models will be far out of sync with the current data. """ metadata = MetaData() metadata.bind = engine return Table(name, metadata, autoload=True) class InsertFromSelect(UpdateBase): """Form the base for `INSERT INTO table (SELECT ... )` statement.""" def __init__(self, table, select): self.table = table self.select = select @compiles(InsertFromSelect) def visit_insert_from_select(element, compiler, **kw): """Form the `INSERT INTO table (SELECT ... )` statement.""" return "INSERT INTO %s %s" % ( compiler.process(element.table, asfrom=True), compiler.process(element.select)) class ColumnError(Exception): """Error raised when no column or an invalid column is found.""" def _get_not_supported_column(col_name_col_instance, column_name): try: column = col_name_col_instance[column_name] except KeyError: msg = _("Please specify column %s in col_name_col_instance " "param. It is required because column has unsupported " "type by sqlite).") raise ColumnError(msg % column_name) if not isinstance(column, Column): msg = _("col_name_col_instance param has wrong type of " "column instance for column %s It should be instance " "of sqlalchemy.Column.") raise ColumnError(msg % column_name) return column def drop_unique_constraint(migrate_engine, table_name, uc_name, *columns, **col_name_col_instance): """Drop unique constraint from table. DEPRECATED: this function is deprecated and will be removed from keystone.db in a few releases. Please use UniqueConstraint.drop() method directly for sqlalchemy-migrate migration scripts. This method drops UC from table and works for mysql, postgresql and sqlite. In mysql and postgresql we are able to use "alter table" construction. Sqlalchemy doesn't support some sqlite column types and replaces their type with NullType in metadata. We process these columns and replace NullType with the correct column type. :param migrate_engine: sqlalchemy engine :param table_name: name of table that contains uniq constraint. :param uc_name: name of uniq constraint that will be dropped. :param columns: columns that are in uniq constraint. :param col_name_col_instance: contains pair column_name=column_instance. column_instance is instance of Column. These params are required only for columns that have unsupported types by sqlite. For example BigInteger. """ from migrate.changeset import UniqueConstraint meta = MetaData() meta.bind = migrate_engine t = Table(table_name, meta, autoload=True) if migrate_engine.name == "sqlite": override_cols = [ _get_not_supported_column(col_name_col_instance, col.name) for col in t.columns if isinstance(col.type, NullType) ] for col in override_cols: t.columns.replace(col) uc = UniqueConstraint(*columns, table=t, name=uc_name) uc.drop() def drop_old_duplicate_entries_from_table(migrate_engine, table_name, use_soft_delete, *uc_column_names): """Drop all old rows having the same values for columns in uc_columns. This method drop (or mark ad `deleted` if use_soft_delete is True) old duplicate rows form table with name `table_name`. :param migrate_engine: Sqlalchemy engine :param table_name: Table with duplicates :param use_soft_delete: If True - values will be marked as `deleted`, if False - values will be removed from table :param uc_column_names: Unique constraint columns """ meta = MetaData() meta.bind = migrate_engine table = Table(table_name, meta, autoload=True) columns_for_group_by = [table.c[name] for name in uc_column_names] columns_for_select = [func.max(table.c.id)] columns_for_select.extend(columns_for_group_by) duplicated_rows_select = sqlalchemy.sql.select( columns_for_select, group_by=columns_for_group_by, having=func.count(table.c.id) > 1) for row in migrate_engine.execute(duplicated_rows_select): # NOTE(boris-42): Do not remove row that has the biggest ID. delete_condition = table.c.id != row[0] is_none = None # workaround for pyflakes delete_condition &= table.c.deleted_at == is_none for name in uc_column_names: delete_condition &= table.c[name] == row[name] rows_to_delete_select = sqlalchemy.sql.select( [table.c.id]).where(delete_condition) for row in migrate_engine.execute(rows_to_delete_select).fetchall(): LOG.info(_LI("Deleting duplicated row with id: %(id)s from table: " "%(table)s") % dict(id=row[0], table=table_name)) if use_soft_delete: delete_statement = table.update().\ where(delete_condition).\ values({ 'deleted': literal_column('id'), 'updated_at': literal_column('updated_at'), 'deleted_at': timeutils.utcnow() }) else: delete_statement = table.delete().where(delete_condition) migrate_engine.execute(delete_statement) def _get_default_deleted_value(table): if isinstance(table.c.id.type, Integer): return 0 if isinstance(table.c.id.type, String): return "" raise ColumnError(_("Unsupported id columns type")) def _restore_indexes_on_deleted_columns(migrate_engine, table_name, indexes): table = get_table(migrate_engine, table_name) insp = reflection.Inspector.from_engine(migrate_engine) real_indexes = insp.get_indexes(table_name) existing_index_names = dict( [(index['name'], index['column_names']) for index in real_indexes]) # NOTE(boris-42): Restore indexes on `deleted` column for index in indexes: if 'deleted' not in index['column_names']: continue name = index['name'] if name in existing_index_names: column_names = [table.c[c] for c in existing_index_names[name]] old_index = Index(name, *column_names, unique=index["unique"]) old_index.drop(migrate_engine) column_names = [table.c[c] for c in index['column_names']] new_index = Index(index["name"], *column_names, unique=index["unique"]) new_index.create(migrate_engine) def change_deleted_column_type_to_boolean(migrate_engine, table_name, **col_name_col_instance): if migrate_engine.name == "sqlite": return _change_deleted_column_type_to_boolean_sqlite( migrate_engine, table_name, **col_name_col_instance) insp = reflection.Inspector.from_engine(migrate_engine) indexes = insp.get_indexes(table_name) table = get_table(migrate_engine, table_name) old_deleted = Column('old_deleted', Boolean, default=False) old_deleted.create(table, populate_default=False) table.update().\ where(table.c.deleted == table.c.id).\ values(old_deleted=True).\ execute() table.c.deleted.drop() table.c.old_deleted.alter(name="deleted") _restore_indexes_on_deleted_columns(migrate_engine, table_name, indexes) def _change_deleted_column_type_to_boolean_sqlite(migrate_engine, table_name, **col_name_col_instance): insp = reflection.Inspector.from_engine(migrate_engine) table = get_table(migrate_engine, table_name) columns = [] for column in table.columns: column_copy = None if column.name != "deleted": if isinstance(column.type, NullType): column_copy = _get_not_supported_column(col_name_col_instance, column.name) else: column_copy = column.copy() else: column_copy = Column('deleted', Boolean, default=0) columns.append(column_copy) constraints = [constraint.copy() for constraint in table.constraints] meta = table.metadata new_table = Table(table_name + "__tmp__", meta, *(columns + constraints)) new_table.create() indexes = [] for index in insp.get_indexes(table_name): column_names = [new_table.c[c] for c in index['column_names']] indexes.append(Index(index["name"], *column_names, unique=index["unique"])) c_select = [] for c in table.c: if c.name != "deleted": c_select.append(c) else: c_select.append(table.c.deleted == table.c.id) ins = InsertFromSelect(new_table, sqlalchemy.sql.select(c_select)) migrate_engine.execute(ins) table.drop() [index.create(migrate_engine) for index in indexes] new_table.rename(table_name) new_table.update().\ where(new_table.c.deleted == new_table.c.id).\ values(deleted=True).\ execute() def change_deleted_column_type_to_id_type(migrate_engine, table_name, **col_name_col_instance): if migrate_engine.name == "sqlite": return _change_deleted_column_type_to_id_type_sqlite( migrate_engine, table_name, **col_name_col_instance) insp = reflection.Inspector.from_engine(migrate_engine) indexes = insp.get_indexes(table_name) table = get_table(migrate_engine, table_name) new_deleted = Column('new_deleted', table.c.id.type, default=_get_default_deleted_value(table)) new_deleted.create(table, populate_default=True) deleted = True # workaround for pyflakes table.update().\ where(table.c.deleted == deleted).\ values(new_deleted=table.c.id).\ execute() table.c.deleted.drop() table.c.new_deleted.alter(name="deleted") _restore_indexes_on_deleted_columns(migrate_engine, table_name, indexes) def _change_deleted_column_type_to_id_type_sqlite(migrate_engine, table_name, **col_name_col_instance): # NOTE(boris-42): sqlaclhemy-migrate can't drop column with check # constraints in sqlite DB and our `deleted` column has # 2 check constraints. So there is only one way to remove # these constraints: # 1) Create new table with the same columns, constraints # and indexes. (except deleted column). # 2) Copy all data from old to new table. # 3) Drop old table. # 4) Rename new table to old table name. insp = reflection.Inspector.from_engine(migrate_engine) meta = MetaData(bind=migrate_engine) table = Table(table_name, meta, autoload=True) default_deleted_value = _get_default_deleted_value(table) columns = [] for column in table.columns: column_copy = None if column.name != "deleted": if isinstance(column.type, NullType): column_copy = _get_not_supported_column(col_name_col_instance, column.name) else: column_copy = column.copy() else: column_copy = Column('deleted', table.c.id.type, default=default_deleted_value) columns.append(column_copy) def is_deleted_column_constraint(constraint): # NOTE(boris-42): There is no other way to check is CheckConstraint # associated with deleted column. if not isinstance(constraint, CheckConstraint): return False sqltext = str(constraint.sqltext) return (sqltext.endswith("deleted in (0, 1)") or sqltext.endswith("deleted IN (:deleted_1, :deleted_2)")) constraints = [] for constraint in table.constraints: if not is_deleted_column_constraint(constraint): constraints.append(constraint.copy()) new_table = Table(table_name + "__tmp__", meta, *(columns + constraints)) new_table.create() indexes = [] for index in insp.get_indexes(table_name): column_names = [new_table.c[c] for c in index['column_names']] indexes.append(Index(index["name"], *column_names, unique=index["unique"])) ins = InsertFromSelect(new_table, table.select()) migrate_engine.execute(ins) table.drop() [index.create(migrate_engine) for index in indexes] new_table.rename(table_name) deleted = True # workaround for pyflakes new_table.update().\ where(new_table.c.deleted == deleted).\ values(deleted=new_table.c.id).\ execute() # NOTE(boris-42): Fix value of deleted column: False -> "" or 0. deleted = False # workaround for pyflakes new_table.update().\ where(new_table.c.deleted == deleted).\ values(deleted=default_deleted_value).\ execute() def get_connect_string(backend, database, user=None, passwd=None): """Get database connection Try to get a connection with a very specific set of values, if we get these then we'll run the tests, otherwise they are skipped """ args = {'backend': backend, 'user': user, 'passwd': passwd, 'database': database} if backend == 'sqlite': template = '%(backend)s:///%(database)s' else: template = "%(backend)s://%(user)s:%(passwd)s@localhost/%(database)s" return template % args def is_backend_avail(backend, database, user=None, passwd=None): try: connect_uri = get_connect_string(backend=backend, database=database, user=user, passwd=passwd) engine = sqlalchemy.create_engine(connect_uri) connection = engine.connect() except Exception: # intentionally catch all to handle exceptions even if we don't # have any backend code loaded. return False else: connection.close() engine.dispose() return True def get_db_connection_info(conn_pieces): database = conn_pieces.path.strip('/') loc_pieces = conn_pieces.netloc.split('@') host = loc_pieces[1] auth_pieces = loc_pieces[0].split(':') user = auth_pieces[0] password = "" if len(auth_pieces) > 1: password = auth_pieces[1].strip() return (user, password, database, host) keystone-2014.1/keystone/openstack/common/db/sqlalchemy/provision.py0000664000175400017540000001147312323716267027070 0ustar jenkinsjenkins00000000000000# Copyright 2013 Mirantis.inc # All Rights Reserved. # # 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. """Provision test environment for specific DB backends""" import argparse import logging import os import random import string from six import moves import sqlalchemy from keystone.openstack.common.db import exception as exc LOG = logging.getLogger(__name__) def get_engine(uri): """Engine creation Call the function without arguments to get admin connection. Admin connection required to create temporary user and database for each particular test. Otherwise use existing connection to recreate connection to the temporary database. """ return sqlalchemy.create_engine(uri, poolclass=sqlalchemy.pool.NullPool) def _execute_sql(engine, sql, driver): """Initialize connection, execute sql query and close it.""" try: with engine.connect() as conn: if driver == 'postgresql': conn.connection.set_isolation_level(0) for s in sql: conn.execute(s) except sqlalchemy.exc.OperationalError: msg = ('%s does not match database admin ' 'credentials or database does not exist.') LOG.exception(msg % engine.url) raise exc.DBConnectionError(msg % engine.url) def create_database(engine): """Provide temporary user and database for each particular test.""" driver = engine.name auth = { 'database': ''.join(random.choice(string.ascii_lowercase) for i in moves.range(10)), 'user': engine.url.username, 'passwd': engine.url.password, } sqls = [ "drop database if exists %(database)s;", "create database %(database)s;" ] if driver == 'sqlite': return 'sqlite:////tmp/%s' % auth['database'] elif driver in ['mysql', 'postgresql']: sql_query = map(lambda x: x % auth, sqls) _execute_sql(engine, sql_query, driver) else: raise ValueError('Unsupported RDBMS %s' % driver) params = auth.copy() params['backend'] = driver return "%(backend)s://%(user)s:%(passwd)s@localhost/%(database)s" % params def drop_database(admin_engine, current_uri): """Drop temporary database and user after each particular test.""" engine = get_engine(current_uri) driver = engine.name auth = {'database': engine.url.database, 'user': engine.url.username} if driver == 'sqlite': try: os.remove(auth['database']) except OSError: pass elif driver in ['mysql', 'postgresql']: sql = "drop database if exists %(database)s;" _execute_sql(admin_engine, [sql % auth], driver) else: raise ValueError('Unsupported RDBMS %s' % driver) def main(): """Controller to handle commands ::create: Create test user and database with random names. ::drop: Drop user and database created by previous command. """ parser = argparse.ArgumentParser( description='Controller to handle database creation and dropping' ' commands.', epilog='Under normal circumstances is not used directly.' ' Used in .testr.conf to automate test database creation' ' and dropping processes.') subparsers = parser.add_subparsers( help='Subcommands to manipulate temporary test databases.') create = subparsers.add_parser( 'create', help='Create temporary test ' 'databases and users.') create.set_defaults(which='create') create.add_argument( 'instances_count', type=int, help='Number of databases to create.') drop = subparsers.add_parser( 'drop', help='Drop temporary test databases and users.') drop.set_defaults(which='drop') drop.add_argument( 'instances', nargs='+', help='List of databases uri to be dropped.') args = parser.parse_args() connection_string = os.getenv('OS_TEST_DBAPI_ADMIN_CONNECTION', 'sqlite://') engine = get_engine(connection_string) which = args.which if which == "create": for i in range(int(args.instances_count)): print(create_database(engine)) elif which == "drop": for db in args.instances: drop_database(engine, db) if __name__ == "__main__": main() keystone-2014.1/keystone/openstack/common/db/sqlalchemy/models.py0000664000175400017540000000755612323716267026332 0ustar jenkinsjenkins00000000000000# Copyright (c) 2011 X.commerce, a business unit of eBay Inc. # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2011 Piston Cloud Computing, Inc. # Copyright 2012 Cloudscaling Group, Inc. # All Rights Reserved. # # 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. """ SQLAlchemy models. """ import six from sqlalchemy import Column, Integer from sqlalchemy import DateTime from sqlalchemy.orm import object_mapper from keystone.openstack.common import timeutils class ModelBase(six.Iterator): """Base class for models.""" __table_initialized__ = False def save(self, session): """Save this object.""" # NOTE(boris-42): This part of code should be look like: # session.add(self) # session.flush() # But there is a bug in sqlalchemy and eventlet that # raises NoneType exception if there is no running # transaction and rollback is called. As long as # sqlalchemy has this bug we have to create transaction # explicitly. with session.begin(subtransactions=True): session.add(self) session.flush() def __setitem__(self, key, value): setattr(self, key, value) def __getitem__(self, key): return getattr(self, key) def get(self, key, default=None): return getattr(self, key, default) @property def _extra_keys(self): """Specifies custom fields Subclasses can override this property to return a list of custom fields that should be included in their dict representation. For reference check tests/db/sqlalchemy/test_models.py """ return [] def __iter__(self): columns = dict(object_mapper(self).columns).keys() # NOTE(russellb): Allow models to specify other keys that can be looked # up, beyond the actual db columns. An example would be the 'name' # property for an Instance. columns.extend(self._extra_keys) self._i = iter(columns) return self # In Python 3, __next__() has replaced next(). def __next__(self): n = six.advance_iterator(self._i) return n, getattr(self, n) def next(self): return self.__next__() def update(self, values): """Make the model object behave like a dict.""" for k, v in six.iteritems(values): setattr(self, k, v) def iteritems(self): """Make the model object behave like a dict. Includes attributes from joins. """ local = dict(self) joined = dict([(k, v) for k, v in six.iteritems(self.__dict__) if not k[0] == '_']) local.update(joined) return six.iteritems(local) class TimestampMixin(object): created_at = Column(DateTime, default=lambda: timeutils.utcnow()) updated_at = Column(DateTime, onupdate=lambda: timeutils.utcnow()) class SoftDeleteMixin(object): deleted_at = Column(DateTime) deleted = Column(Integer, default=0) def soft_delete(self, session): """Mark this object as deleted.""" self.deleted = self.id self.deleted_at = timeutils.utcnow() self.save(session=session) keystone-2014.1/keystone/openstack/common/db/sqlalchemy/test_base.py0000664000175400017540000001154012323716267027004 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import abc import functools import os import fixtures import six from keystone.openstack.common.db.sqlalchemy import session from keystone.openstack.common.db.sqlalchemy import utils from keystone.openstack.common.fixture import lockutils from keystone.openstack.common import test class DbFixture(fixtures.Fixture): """Basic database fixture. Allows to run tests on various db backends, such as SQLite, MySQL and PostgreSQL. By default use sqlite backend. To override default backend uri set env variable OS_TEST_DBAPI_CONNECTION with database admin credentials for specific backend. """ def _get_uri(self): return os.getenv('OS_TEST_DBAPI_CONNECTION', 'sqlite://') def __init__(self, test): super(DbFixture, self).__init__() self.test = test def setUp(self): super(DbFixture, self).setUp() self.test.engine = session.create_engine(self._get_uri()) self.test.sessionmaker = session.get_maker(self.test.engine) self.addCleanup(self.test.engine.dispose) class DbTestCase(test.BaseTestCase): """Base class for testing of DB code. Using `DbFixture`. Intended to be the main database test case to use all the tests on a given backend with user defined uri. Backend specific tests should be decorated with `backend_specific` decorator. """ FIXTURE = DbFixture def setUp(self): super(DbTestCase, self).setUp() self.useFixture(self.FIXTURE(self)) ALLOWED_DIALECTS = ['sqlite', 'mysql', 'postgresql'] def backend_specific(*dialects): """Decorator to skip backend specific tests on inappropriate engines. ::dialects: list of dialects names under which the test will be launched. """ def wrap(f): @functools.wraps(f) def ins_wrap(self): if not set(dialects).issubset(ALLOWED_DIALECTS): raise ValueError( "Please use allowed dialects: %s" % ALLOWED_DIALECTS) if self.engine.name not in dialects: msg = ('The test "%s" can be run ' 'only on %s. Current engine is %s.') args = (f.__name__, ' '.join(dialects), self.engine.name) self.skip(msg % args) else: return f(self) return ins_wrap return wrap @six.add_metaclass(abc.ABCMeta) class OpportunisticFixture(DbFixture): """Base fixture to use default CI databases. The databases exist in OpenStack CI infrastructure. But for the correct functioning in local environment the databases must be created manually. """ DRIVER = abc.abstractproperty(lambda: None) DBNAME = PASSWORD = USERNAME = 'openstack_citest' def _get_uri(self): return utils.get_connect_string(backend=self.DRIVER, user=self.USERNAME, passwd=self.PASSWORD, database=self.DBNAME) @six.add_metaclass(abc.ABCMeta) class OpportunisticTestCase(DbTestCase): """Base test case to use default CI databases. The subclasses of the test case are running only when openstack_citest database is available otherwise a tests will be skipped. """ FIXTURE = abc.abstractproperty(lambda: None) def setUp(self): # TODO(bnemec): Remove this once infra is ready for # https://review.openstack.org/#/c/74963/ to merge. self.useFixture(lockutils.LockFixture('opportunistic-db')) credentials = { 'backend': self.FIXTURE.DRIVER, 'user': self.FIXTURE.USERNAME, 'passwd': self.FIXTURE.PASSWORD, 'database': self.FIXTURE.DBNAME} if self.FIXTURE.DRIVER and not utils.is_backend_avail(**credentials): msg = '%s backend is not available.' % self.FIXTURE.DRIVER return self.skip(msg) super(OpportunisticTestCase, self).setUp() class MySQLOpportunisticFixture(OpportunisticFixture): DRIVER = 'mysql' class PostgreSQLOpportunisticFixture(OpportunisticFixture): DRIVER = 'postgresql' class MySQLOpportunisticTestCase(OpportunisticTestCase): FIXTURE = MySQLOpportunisticFixture class PostgreSQLOpportunisticTestCase(OpportunisticTestCase): FIXTURE = PostgreSQLOpportunisticFixture keystone-2014.1/keystone/openstack/common/db/sqlalchemy/test_migrations.py0000664000175400017540000002551312323716267030253 0ustar jenkinsjenkins00000000000000# Copyright 2010-2011 OpenStack Foundation # Copyright 2012-2013 IBM Corp. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import functools import logging import os import subprocess import lockfile from six import moves from six.moves.urllib import parse import sqlalchemy import sqlalchemy.exc from keystone.openstack.common.db.sqlalchemy import utils from keystone.openstack.common.gettextutils import _LE from keystone.openstack.common import test LOG = logging.getLogger(__name__) def _have_mysql(user, passwd, database): present = os.environ.get('TEST_MYSQL_PRESENT') if present is None: return utils.is_backend_avail(backend='mysql', user=user, passwd=passwd, database=database) return present.lower() in ('', 'true') def _have_postgresql(user, passwd, database): present = os.environ.get('TEST_POSTGRESQL_PRESENT') if present is None: return utils.is_backend_avail(backend='postgres', user=user, passwd=passwd, database=database) return present.lower() in ('', 'true') def _set_db_lock(lock_path=None, lock_prefix=None): def decorator(f): @functools.wraps(f) def wrapper(*args, **kwargs): try: path = lock_path or os.environ.get("KEYSTONE_LOCK_PATH") lock = lockfile.FileLock(os.path.join(path, lock_prefix)) with lock: LOG.debug('Got lock "%s"' % f.__name__) return f(*args, **kwargs) finally: LOG.debug('Lock released "%s"' % f.__name__) return wrapper return decorator class BaseMigrationTestCase(test.BaseTestCase): """Base class fort testing of migration utils.""" def __init__(self, *args, **kwargs): super(BaseMigrationTestCase, self).__init__(*args, **kwargs) self.DEFAULT_CONFIG_FILE = os.path.join(os.path.dirname(__file__), 'test_migrations.conf') # Test machines can set the TEST_MIGRATIONS_CONF variable # to override the location of the config file for migration testing self.CONFIG_FILE_PATH = os.environ.get('TEST_MIGRATIONS_CONF', self.DEFAULT_CONFIG_FILE) self.test_databases = {} self.migration_api = None def setUp(self): super(BaseMigrationTestCase, self).setUp() # Load test databases from the config file. Only do this # once. No need to re-run this on each test... LOG.debug('config_path is %s' % self.CONFIG_FILE_PATH) if os.path.exists(self.CONFIG_FILE_PATH): cp = moves.configparser.RawConfigParser() try: cp.read(self.CONFIG_FILE_PATH) defaults = cp.defaults() for key, value in defaults.items(): self.test_databases[key] = value except moves.configparser.ParsingError as e: self.fail("Failed to read test_migrations.conf config " "file. Got error: %s" % e) else: self.fail("Failed to find test_migrations.conf config " "file.") self.engines = {} for key, value in self.test_databases.items(): self.engines[key] = sqlalchemy.create_engine(value) # We start each test case with a completely blank slate. self._reset_databases() def tearDown(self): # We destroy the test data store between each test case, # and recreate it, which ensures that we have no side-effects # from the tests self._reset_databases() super(BaseMigrationTestCase, self).tearDown() def execute_cmd(self, cmd=None): process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output = process.communicate()[0] LOG.debug(output) self.assertEqual(0, process.returncode, "Failed to run: %s\n%s" % (cmd, output)) def _reset_pg(self, conn_pieces): (user, password, database, host) = utils.get_db_connection_info(conn_pieces) os.environ['PGPASSWORD'] = password os.environ['PGUSER'] = user # note(boris-42): We must create and drop database, we can't # drop database which we have connected to, so for such # operations there is a special database template1. sqlcmd = ("psql -w -U %(user)s -h %(host)s -c" " '%(sql)s' -d template1") sql = ("drop database if exists %s;") % database droptable = sqlcmd % {'user': user, 'host': host, 'sql': sql} self.execute_cmd(droptable) sql = ("create database %s;") % database createtable = sqlcmd % {'user': user, 'host': host, 'sql': sql} self.execute_cmd(createtable) os.unsetenv('PGPASSWORD') os.unsetenv('PGUSER') @_set_db_lock(lock_prefix='migration_tests-') def _reset_databases(self): for key, engine in self.engines.items(): conn_string = self.test_databases[key] conn_pieces = parse.urlparse(conn_string) engine.dispose() if conn_string.startswith('sqlite'): # We can just delete the SQLite database, which is # the easiest and cleanest solution db_path = conn_pieces.path.strip('/') if os.path.exists(db_path): os.unlink(db_path) # No need to recreate the SQLite DB. SQLite will # create it for us if it's not there... elif conn_string.startswith('mysql'): # We can execute the MySQL client to destroy and re-create # the MYSQL database, which is easier and less error-prone # than using SQLAlchemy to do this via MetaData...trust me. (user, password, database, host) = \ utils.get_db_connection_info(conn_pieces) sql = ("drop database if exists %(db)s; " "create database %(db)s;") % {'db': database} cmd = ("mysql -u \"%(user)s\" -p\"%(password)s\" -h %(host)s " "-e \"%(sql)s\"") % {'user': user, 'password': password, 'host': host, 'sql': sql} self.execute_cmd(cmd) elif conn_string.startswith('postgresql'): self._reset_pg(conn_pieces) class WalkVersionsMixin(object): def _walk_versions(self, engine=None, snake_walk=False, downgrade=True): # Determine latest version script from the repo, then # upgrade from 1 through to the latest, with no data # in the databases. This just checks that the schema itself # upgrades successfully. # Place the database under version control self.migration_api.version_control(engine, self.REPOSITORY, self.INIT_VERSION) self.assertEqual(self.INIT_VERSION, self.migration_api.db_version(engine, self.REPOSITORY)) LOG.debug('latest version is %s' % self.REPOSITORY.latest) versions = range(self.INIT_VERSION + 1, self.REPOSITORY.latest + 1) for version in versions: # upgrade -> downgrade -> upgrade self._migrate_up(engine, version, with_data=True) if snake_walk: downgraded = self._migrate_down( engine, version - 1, with_data=True) if downgraded: self._migrate_up(engine, version) if downgrade: # Now walk it back down to 0 from the latest, testing # the downgrade paths. for version in reversed(versions): # downgrade -> upgrade -> downgrade downgraded = self._migrate_down(engine, version - 1) if snake_walk and downgraded: self._migrate_up(engine, version) self._migrate_down(engine, version - 1) def _migrate_down(self, engine, version, with_data=False): try: self.migration_api.downgrade(engine, self.REPOSITORY, version) except NotImplementedError: # NOTE(sirp): some migrations, namely release-level # migrations, don't support a downgrade. return False self.assertEqual( version, self.migration_api.db_version(engine, self.REPOSITORY)) # NOTE(sirp): `version` is what we're downgrading to (i.e. the 'target' # version). So if we have any downgrade checks, they need to be run for # the previous (higher numbered) migration. if with_data: post_downgrade = getattr( self, "_post_downgrade_%03d" % (version + 1), None) if post_downgrade: post_downgrade(engine) return True def _migrate_up(self, engine, version, with_data=False): """migrate up to a new version of the db. We allow for data insertion and post checks at every migration version with special _pre_upgrade_### and _check_### functions in the main test. """ # NOTE(sdague): try block is here because it's impossible to debug # where a failed data migration happens otherwise try: if with_data: data = None pre_upgrade = getattr( self, "_pre_upgrade_%03d" % version, None) if pre_upgrade: data = pre_upgrade(engine) self.migration_api.upgrade(engine, self.REPOSITORY, version) self.assertEqual(version, self.migration_api.db_version(engine, self.REPOSITORY)) if with_data: check = getattr(self, "_check_%03d" % version, None) if check: check(engine, data) except Exception: LOG.error(_LE("Failed to migrate to version %s on engine %s") % (version, engine)) raise keystone-2014.1/keystone/openstack/common/db/sqlalchemy/__init__.py0000664000175400017540000000000012323716267026557 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/db/exception.py0000664000175400017540000000352212323716267024670 0ustar jenkinsjenkins00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """DB related custom exceptions.""" import six from keystone.openstack.common.gettextutils import _ class DBError(Exception): """Wraps an implementation specific exception.""" def __init__(self, inner_exception=None): self.inner_exception = inner_exception super(DBError, self).__init__(six.text_type(inner_exception)) class DBDuplicateEntry(DBError): """Wraps an implementation specific exception.""" def __init__(self, columns=[], inner_exception=None): self.columns = columns super(DBDuplicateEntry, self).__init__(inner_exception) class DBDeadlock(DBError): def __init__(self, inner_exception=None): super(DBDeadlock, self).__init__(inner_exception) class DBInvalidUnicodeParameter(Exception): message = _("Invalid Parameter: " "Unicode is not supported by the current database.") class DbMigrationError(DBError): """Wraps migration specific exception.""" def __init__(self, message=None): super(DbMigrationError, self).__init__(message) class DBConnectionError(DBError): """Wraps connection specific exception.""" pass keystone-2014.1/keystone/openstack/common/db/api.py0000664000175400017540000001355012323716267023445 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 Rackspace Hosting # All Rights Reserved. # # 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. """Multiple DB API backend support. A DB backend module should implement a method named 'get_backend' which takes no arguments. The method can return any object that implements DB API methods. """ import functools import logging import threading import time from keystone.openstack.common.db import exception from keystone.openstack.common.gettextutils import _LE from keystone.openstack.common import importutils LOG = logging.getLogger(__name__) def safe_for_db_retry(f): """Enable db-retry for decorated function, if config option enabled.""" f.__dict__['enable_retry'] = True return f class wrap_db_retry(object): """Retry db.api methods, if DBConnectionError() raised Retry decorated db.api methods. If we enabled `use_db_reconnect` in config, this decorator will be applied to all db.api functions, marked with @safe_for_db_retry decorator. Decorator catchs DBConnectionError() and retries function in a loop until it succeeds, or until maximum retries count will be reached. """ def __init__(self, retry_interval, max_retries, inc_retry_interval, max_retry_interval): super(wrap_db_retry, self).__init__() self.retry_interval = retry_interval self.max_retries = max_retries self.inc_retry_interval = inc_retry_interval self.max_retry_interval = max_retry_interval def __call__(self, f): @functools.wraps(f) def wrapper(*args, **kwargs): next_interval = self.retry_interval remaining = self.max_retries while True: try: return f(*args, **kwargs) except exception.DBConnectionError as e: if remaining == 0: LOG.exception(_LE('DB exceeded retry limit.')) raise exception.DBError(e) if remaining != -1: remaining -= 1 LOG.exception(_LE('DB connection error.')) # NOTE(vsergeyev): We are using patched time module, so # this effectively yields the execution # context to another green thread. time.sleep(next_interval) if self.inc_retry_interval: next_interval = min( next_interval * 2, self.max_retry_interval ) return wrapper class DBAPI(object): def __init__(self, backend_name, backend_mapping=None, lazy=False, **kwargs): """Initialize the chosen DB API backend. :param backend_name: name of the backend to load :type backend_name: str :param backend_mapping: backend name -> module/class to load mapping :type backend_mapping: dict :param lazy: load the DB backend lazily on the first DB API method call :type lazy: bool Keyword arguments: :keyword use_db_reconnect: retry DB transactions on disconnect or not :type use_db_reconnect: bool :keyword retry_interval: seconds between transaction retries :type retry_interval: int :keyword inc_retry_interval: increase retry interval or not :type inc_retry_interval: bool :keyword max_retry_interval: max interval value between retries :type max_retry_interval: int :keyword max_retries: max number of retries before an error is raised :type max_retries: int """ self._backend = None self._backend_name = backend_name self._backend_mapping = backend_mapping or {} self._lock = threading.Lock() if not lazy: self._load_backend() self.use_db_reconnect = kwargs.get('use_db_reconnect', False) self.retry_interval = kwargs.get('retry_interval', 1) self.inc_retry_interval = kwargs.get('inc_retry_interval', True) self.max_retry_interval = kwargs.get('max_retry_interval', 10) self.max_retries = kwargs.get('max_retries', 20) def _load_backend(self): with self._lock: if not self._backend: # Import the untranslated name if we don't have a mapping backend_path = self._backend_mapping.get(self._backend_name, self._backend_name) backend_mod = importutils.import_module(backend_path) self._backend = backend_mod.get_backend() def __getattr__(self, key): if not self._backend: self._load_backend() attr = getattr(self._backend, key) if not hasattr(attr, '__call__'): return attr # NOTE(vsergeyev): If `use_db_reconnect` option is set to True, retry # DB API methods, decorated with @safe_for_db_retry # on disconnect. if self.use_db_reconnect and hasattr(attr, 'enable_retry'): attr = wrap_db_retry( retry_interval=self.retry_interval, max_retries=self.max_retries, inc_retry_interval=self.inc_retry_interval, max_retry_interval=self.max_retry_interval)(attr) return attr keystone-2014.1/keystone/openstack/common/db/__init__.py0000664000175400017540000000000012323716267024415 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/openstack/common/__init__.py0000664000175400017540000000120412323716267024037 0ustar jenkinsjenkins00000000000000# # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import six six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) keystone-2014.1/keystone/openstack/common/uuidutils.py0000664000175400017540000000212212323716267024327 0ustar jenkinsjenkins00000000000000# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 Intel Corporation. # All Rights Reserved. # # 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. """ UUID related utilities and helper functions. """ import uuid def generate_uuid(): return str(uuid.uuid4()) def is_uuid_like(val): """Returns validation of a value as a UUID. For our purposes, a UUID is a canonical form string: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa """ try: return str(uuid.UUID(val)) == val except (TypeError, ValueError, AttributeError): return False keystone-2014.1/keystone/openstack/__init__.py0000664000175400017540000000000012323716267022540 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/catalog/0000775000175400017540000000000012323716511020054 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/catalog/controllers.py0000664000175400017540000002561012323716267023010 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2012 Canonical Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid import six from keystone.common import controller from keystone.common import dependency from keystone.common import wsgi from keystone import exception from keystone.openstack.common.gettextutils import _ INTERFACES = ['public', 'internal', 'admin'] @dependency.requires('catalog_api') class Service(controller.V2Controller): @controller.v2_deprecated def get_services(self, context): self.assert_admin(context) service_list = self.catalog_api.list_services() return {'OS-KSADM:services': service_list} @controller.v2_deprecated def get_service(self, context, service_id): self.assert_admin(context) service_ref = self.catalog_api.get_service(service_id) return {'OS-KSADM:service': service_ref} @controller.v2_deprecated def delete_service(self, context, service_id): self.assert_admin(context) self.catalog_api.delete_service(service_id) @controller.v2_deprecated def create_service(self, context, OS_KSADM_service): self.assert_admin(context) service_id = uuid.uuid4().hex service_ref = OS_KSADM_service.copy() service_ref['id'] = service_id new_service_ref = self.catalog_api.create_service( service_id, service_ref) return {'OS-KSADM:service': new_service_ref} @dependency.requires('catalog_api') class Endpoint(controller.V2Controller): @controller.v2_deprecated def get_endpoints(self, context): """Merge matching v3 endpoint refs into legacy refs.""" self.assert_admin(context) legacy_endpoints = {} for endpoint in self.catalog_api.list_endpoints(): if not endpoint.get('legacy_endpoint_id'): # endpoints created in v3 should not appear on the v2 API continue # is this is a legacy endpoint we haven't indexed yet? if endpoint['legacy_endpoint_id'] not in legacy_endpoints: legacy_ep = endpoint.copy() legacy_ep['id'] = legacy_ep.pop('legacy_endpoint_id') legacy_ep.pop('interface') legacy_ep.pop('url') legacy_endpoints[endpoint['legacy_endpoint_id']] = legacy_ep else: legacy_ep = legacy_endpoints[endpoint['legacy_endpoint_id']] # add the legacy endpoint with an interface url legacy_ep['%surl' % endpoint['interface']] = endpoint['url'] return {'endpoints': legacy_endpoints.values()} @controller.v2_deprecated def create_endpoint(self, context, endpoint): """Create three v3 endpoint refs based on a legacy ref.""" self.assert_admin(context) # according to the v2 spec publicurl is mandatory self._require_attribute(endpoint, 'publicurl') # service_id is necessary self._require_attribute(endpoint, 'service_id') legacy_endpoint_ref = endpoint.copy() urls = {} for i in INTERFACES: # remove all urls so they aren't persisted them more than once url = '%surl' % i if endpoint.get(url): # valid urls need to be persisted urls[i] = endpoint.pop(url) elif url in endpoint: # null or empty urls can be discarded endpoint.pop(url) legacy_endpoint_ref.pop(url) legacy_endpoint_id = uuid.uuid4().hex for interface, url in six.iteritems(urls): endpoint_ref = endpoint.copy() endpoint_ref['id'] = uuid.uuid4().hex endpoint_ref['legacy_endpoint_id'] = legacy_endpoint_id endpoint_ref['interface'] = interface endpoint_ref['url'] = url self.catalog_api.create_endpoint(endpoint_ref['id'], endpoint_ref) legacy_endpoint_ref['id'] = legacy_endpoint_id return {'endpoint': legacy_endpoint_ref} @controller.v2_deprecated def delete_endpoint(self, context, endpoint_id): """Delete up to three v3 endpoint refs based on a legacy ref ID.""" self.assert_admin(context) deleted_at_least_one = False for endpoint in self.catalog_api.list_endpoints(): if endpoint['legacy_endpoint_id'] == endpoint_id: self.catalog_api.delete_endpoint(endpoint['id']) deleted_at_least_one = True if not deleted_at_least_one: raise exception.EndpointNotFound(endpoint_id=endpoint_id) @dependency.requires('catalog_api') class RegionV3(controller.V3Controller): collection_name = 'regions' member_name = 'region' def create_region_with_id(self, context, region_id, region): """Create a region with a user-specified ID. This method is unprotected because it depends on ``self.create_region`` to enforce policy. """ if 'id' in region and region_id != region['id']: raise exception.ValidationError( _('Conflicting region IDs specified: ' '"%(url_id)s" != "%(ref_id)s"') % { 'url_id': region_id, 'ref_id': region['id']}) region['id'] = region_id return self.create_region(context, region) @controller.protected() def create_region(self, context, region): ref = self._normalize_dict(region) if 'id' not in ref: ref = self._assign_unique_id(ref) ref = self.catalog_api.create_region(ref) return wsgi.render_response( RegionV3.wrap_member(context, ref), status=(201, 'Created')) @controller.protected() def list_regions(self, context): refs = self.catalog_api.list_regions() return RegionV3.wrap_collection(context, refs) @controller.protected() def get_region(self, context, region_id): ref = self.catalog_api.get_region(region_id) return RegionV3.wrap_member(context, ref) @controller.protected() def update_region(self, context, region_id, region): self._require_matching_id(region_id, region) ref = self.catalog_api.update_region(region_id, region) return RegionV3.wrap_member(context, ref) @controller.protected() def delete_region(self, context, region_id): return self.catalog_api.delete_region(region_id) @dependency.requires('catalog_api') class ServiceV3(controller.V3Controller): collection_name = 'services' member_name = 'service' def __init__(self): super(ServiceV3, self).__init__() self.get_member_from_driver = self.catalog_api.get_service def _validate_service(self, service): if 'enabled' in service and not isinstance(service['enabled'], bool): msg = _('Enabled field must be a boolean') raise exception.ValidationError(message=msg) @controller.protected() def create_service(self, context, service): self._validate_service(service) ref = self._assign_unique_id(self._normalize_dict(service)) self._require_attribute(ref, 'type') ref = self.catalog_api.create_service(ref['id'], ref) return ServiceV3.wrap_member(context, ref) @controller.filterprotected('type') def list_services(self, context, filters): hints = ServiceV3.build_driver_hints(context, filters) refs = self.catalog_api.list_services(hints=hints) return ServiceV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_service(self, context, service_id): ref = self.catalog_api.get_service(service_id) return ServiceV3.wrap_member(context, ref) @controller.protected() def update_service(self, context, service_id, service): self._require_matching_id(service_id, service) self._validate_service(service) ref = self.catalog_api.update_service(service_id, service) return ServiceV3.wrap_member(context, ref) @controller.protected() def delete_service(self, context, service_id): return self.catalog_api.delete_service(service_id) @dependency.requires('catalog_api') class EndpointV3(controller.V3Controller): collection_name = 'endpoints' member_name = 'endpoint' def __init__(self): super(EndpointV3, self).__init__() self.get_member_from_driver = self.catalog_api.get_endpoint @classmethod def filter_endpoint(cls, ref): if 'legacy_endpoint_id' in ref: ref.pop('legacy_endpoint_id') return ref @classmethod def wrap_member(cls, context, ref): ref = cls.filter_endpoint(ref) return super(EndpointV3, cls).wrap_member(context, ref) def _validate_endpoint(self, endpoint): if 'enabled' in endpoint and not isinstance(endpoint['enabled'], bool): msg = _('Enabled field must be a boolean') raise exception.ValidationError(message=msg) @controller.protected() def create_endpoint(self, context, endpoint): self._validate_endpoint(endpoint) ref = self._assign_unique_id(self._normalize_dict(endpoint)) self._require_attribute(ref, 'service_id') self._require_attribute(ref, 'interface') self._require_attribute(ref, 'url') self.catalog_api.get_service(ref['service_id']) ref = self.catalog_api.create_endpoint(ref['id'], ref) return EndpointV3.wrap_member(context, ref) @controller.filterprotected('interface', 'service_id') def list_endpoints(self, context, filters): hints = EndpointV3.build_driver_hints(context, filters) refs = self.catalog_api.list_endpoints(hints=hints) return EndpointV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_endpoint(self, context, endpoint_id): ref = self.catalog_api.get_endpoint(endpoint_id) return EndpointV3.wrap_member(context, ref) @controller.protected() def update_endpoint(self, context, endpoint_id, endpoint): self._require_matching_id(endpoint_id, endpoint) self._validate_endpoint(endpoint) if 'service_id' in endpoint: self.catalog_api.get_service(endpoint['service_id']) ref = self.catalog_api.update_endpoint(endpoint_id, endpoint) return EndpointV3.wrap_member(context, ref) @controller.protected() def delete_endpoint(self, context, endpoint_id): return self.catalog_api.delete_endpoint(endpoint_id) keystone-2014.1/keystone/catalog/core.py0000664000175400017540000002514112323716267021371 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2012 Canonical Ltd. # # 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. """Main entry point into the Catalog service.""" import abc import six from keystone.common import dependency from keystone.common import driver_hints from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) def format_url(url, data): """Safely string formats a user-defined URL with the given data.""" try: result = url.replace('$(', '%(') % data except AttributeError: return None except KeyError as e: LOG.error(_("Malformed endpoint %(url)s - unknown key %(keyerror)s"), {"url": url, "keyerror": e}) raise exception.MalformedEndpoint(endpoint=url) except TypeError as e: LOG.error(_("Malformed endpoint %(url)s - unknown key %(keyerror)s" "(are you missing brackets ?)"), {"url": url, "keyerror": e}) raise exception.MalformedEndpoint(endpoint=url) except ValueError as e: LOG.error(_("Malformed endpoint %s - incomplete format " "(are you missing a type notifier ?)"), url) raise exception.MalformedEndpoint(endpoint=url) return result @dependency.provider('catalog_api') class Manager(manager.Manager): """Default pivot point for the Catalog backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.catalog.driver) def create_region(self, region_ref): # Check duplicate ID try: self.get_region(region_ref['id']) except exception.RegionNotFound: pass else: msg = _('Duplicate ID, %s.') % region_ref['id'] raise exception.Conflict(type='region', details=msg) try: return self.driver.create_region(region_ref) except exception.NotFound: parent_region_id = region_ref.get('parent_region_id') raise exception.RegionNotFound(region_id=parent_region_id) def get_region(self, region_id): try: return self.driver.get_region(region_id) except exception.NotFound: raise exception.RegionNotFound(region_id=region_id) def delete_region(self, region_id): try: return self.driver.delete_region(region_id) except exception.NotFound: raise exception.RegionNotFound(region_id=region_id) def create_service(self, service_id, service_ref): service_ref.setdefault('enabled', True) return self.driver.create_service(service_id, service_ref) def get_service(self, service_id): try: return self.driver.get_service(service_id) except exception.NotFound: raise exception.ServiceNotFound(service_id=service_id) def delete_service(self, service_id): try: return self.driver.delete_service(service_id) except exception.NotFound: raise exception.ServiceNotFound(service_id=service_id) @manager.response_truncated def list_services(self, hints=None): return self.driver.list_services(hints or driver_hints.Hints()) def create_endpoint(self, endpoint_id, endpoint_ref): try: return self.driver.create_endpoint(endpoint_id, endpoint_ref) except exception.NotFound: service_id = endpoint_ref.get('service_id') raise exception.ServiceNotFound(service_id=service_id) def delete_endpoint(self, endpoint_id): try: return self.driver.delete_endpoint(endpoint_id) except exception.NotFound: raise exception.EndpointNotFound(endpoint_id=endpoint_id) def get_endpoint(self, endpoint_id): try: return self.driver.get_endpoint(endpoint_id) except exception.NotFound: raise exception.EndpointNotFound(endpoint_id=endpoint_id) @manager.response_truncated def list_endpoints(self, hints=None): return self.driver.list_endpoints(hints or driver_hints.Hints()) def get_catalog(self, user_id, tenant_id, metadata=None): try: return self.driver.get_catalog(user_id, tenant_id, metadata) except exception.NotFound: raise exception.NotFound('Catalog not found for user and tenant') @six.add_metaclass(abc.ABCMeta) class Driver(object): """Interface description for an Catalog driver.""" def _get_list_limit(self): return CONF.catalog.list_limit or CONF.list_limit @abc.abstractmethod def create_region(self, region_ref): """Creates a new region. :raises: keystone.exception.Conflict :raises: keystone.exception.RegionNotFound (if parent region invalid) """ raise exception.NotImplemented() @abc.abstractmethod def list_regions(self): """List all regions. :returns: list of region_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_region(self, region_id): """Get region by id. :returns: region_ref dict :raises: keystone.exception.RegionNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_region(self, region_id): """Update region by id. :returns: region_ref dict :raises: keystone.exception.RegionNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_region(self, region_id): """Deletes an existing region. :raises: keystone.exception.RegionNotFound """ raise exception.NotImplemented() @abc.abstractmethod def create_service(self, service_id, service_ref): """Creates a new service. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_services(self): """List all services. :returns: list of service_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_service(self, service_id): """Get service by id. :returns: service_ref dict :raises: keystone.exception.ServiceNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_service(self, service_id): """Update service by id. :returns: service_ref dict :raises: keystone.exception.ServiceNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_service(self, service_id): """Deletes an existing service. :raises: keystone.exception.ServiceNotFound """ raise exception.NotImplemented() @abc.abstractmethod def create_endpoint(self, endpoint_id, endpoint_ref): """Creates a new endpoint for a service. :raises: keystone.exception.Conflict, keystone.exception.ServiceNotFound """ raise exception.NotImplemented() @abc.abstractmethod def get_endpoint(self, endpoint_id): """Get endpoint by id. :returns: endpoint_ref dict :raises: keystone.exception.EndpointNotFound """ raise exception.NotImplemented() @abc.abstractmethod def list_endpoints(self): """List all endpoints. :returns: list of endpoint_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def update_endpoint(self, endpoint_id, endpoint_ref): """Get endpoint by id. :returns: endpoint_ref dict :raises: keystone.exception.EndpointNotFound keystone.exception.ServiceNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_endpoint(self, endpoint_id): """Deletes an endpoint for a service. :raises: keystone.exception.EndpointNotFound """ raise exception.NotImplemented() @abc.abstractmethod def get_catalog(self, user_id, tenant_id, metadata=None): """Retrieve and format the current service catalog. Example:: { 'RegionOne': {'compute': { 'adminURL': u'http://host:8774/v1.1/tenantid', 'internalURL': u'http://host:8774/v1.1/tenant_id', 'name': 'Compute Service', 'publicURL': u'http://host:8774/v1.1/tenantid'}, 'ec2': { 'adminURL': 'http://host:8773/services/Admin', 'internalURL': 'http://host:8773/services/Cloud', 'name': 'EC2 Service', 'publicURL': 'http://host:8773/services/Cloud'}} :returns: A nested dict representing the service catalog or an empty dict. :raises: keystone.exception.NotFound """ raise exception.NotImplemented() @abc.abstractmethod def get_v3_catalog(self, user_id, tenant_id, metadata=None): """Retrieve and format the current V3 service catalog. Example:: [ { "endpoints": [ { "interface": "public", "id": "--endpoint-id--", "region": "RegionOne", "url": "http://external:8776/v1/--project-id--" }, { "interface": "internal", "id": "--endpoint-id--", "region": "RegionOne", "url": "http://internal:8776/v1/--project-id--" }], "id": "--service-id--", "type": "volume" }] :returns: A list representing the service catalog or an empty list :raises: keystone.exception.NotFound """ raise exception.NotImplemented() keystone-2014.1/keystone/catalog/routers.py0000664000175400017540000000247512323716267022151 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.catalog import controllers from keystone.common import router def append_v3_routers(mapper, routers): regions_controller = controllers.RegionV3() routers.append(router.Router(regions_controller, 'regions', 'region')) # Need to add an additional route to support PUT /regions/{region_id} mapper.connect( '/regions/{region_id}', controller=regions_controller, action='create_region_with_id', conditions=dict(method=['PUT'])) routers.append(router.Router(controllers.ServiceV3(), 'services', 'service')) routers.append(router.Router(controllers.EndpointV3(), 'endpoints', 'endpoint')) keystone-2014.1/keystone/catalog/backends/0000775000175400017540000000000012323716511021626 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/catalog/backends/sql.py0000664000175400017540000002674712323716272023023 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundation # Copyright 2012 Canonical Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import six import sqlalchemy from keystone import catalog from keystone.catalog import core from keystone.common import sql from keystone.common.sql import migration_helpers from keystone import config from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration CONF = config.CONF class Region(sql.ModelBase, sql.DictBase): __tablename__ = 'region' attributes = ['id', 'description', 'parent_region_id'] id = sql.Column(sql.String(64), primary_key=True) description = sql.Column(sql.String(255)) # NOTE(jaypipes): Right now, using an adjacency list model for # storing the hierarchy of regions is fine, since # the API does not support any kind of querying for # more complex hierarchical queries such as "get me only # the regions that are subchildren of this region", etc. # If, in the future, such queries are needed, then it # would be possible to add in columns to this model for # "left" and "right" and provide support for a nested set # model. parent_region_id = sql.Column(sql.String(64), nullable=True) # TODO(jaypipes): I think it's absolutely stupid that every single model # is required to have an "extra" column because of the # DictBase in the keystone.common.sql.core module. Forcing # tables to have pointless columns in the database is just # bad. Remove all of this extra JSON blob stuff. # See: https://bugs.launchpad.net/keystone/+bug/1265071 extra = sql.Column(sql.JsonBlob()) class Service(sql.ModelBase, sql.DictBase): __tablename__ = 'service' attributes = ['id', 'type', 'enabled'] id = sql.Column(sql.String(64), primary_key=True) type = sql.Column(sql.String(255)) enabled = sql.Column(sql.Boolean, nullable=False, default=True, server_default='1') extra = sql.Column(sql.JsonBlob()) endpoints = sqlalchemy.orm.relationship("Endpoint", backref="service") class Endpoint(sql.ModelBase, sql.DictBase): __tablename__ = 'endpoint' attributes = ['id', 'interface', 'region', 'service_id', 'url', 'legacy_endpoint_id', 'enabled'] id = sql.Column(sql.String(64), primary_key=True) legacy_endpoint_id = sql.Column(sql.String(64)) interface = sql.Column(sql.String(8), nullable=False) region = sql.Column(sql.String(255)) service_id = sql.Column(sql.String(64), sql.ForeignKey('service.id'), nullable=False) url = sql.Column(sql.Text(), nullable=False) enabled = sql.Column(sql.Boolean, nullable=False, default=True, server_default='1') extra = sql.Column(sql.JsonBlob()) class Catalog(catalog.Driver): def db_sync(self, version=None): migration.db_sync( sql.get_engine(), migration_helpers.find_migrate_repo(), version=version) # Regions def list_regions(self): session = sql.get_session() regions = session.query(Region).all() return [s.to_dict() for s in list(regions)] def _get_region(self, session, region_id): ref = session.query(Region).get(region_id) if not ref: raise exception.RegionNotFound(region_id=region_id) return ref def _delete_child_regions(self, session, region_id): """Delete all child regions. Recursively delete any region that has the supplied region as its parent. """ children = session.query(Region).filter_by(parent_region_id=region_id) for child in children: self._delete_child_regions(session, child.id) session.delete(child) def _check_parent_region(self, session, region_ref): """Raise a NotFound if the parent region does not exist. If the region_ref has a specified parent_region_id, check that the parent exists, otherwise, raise a NotFound. """ parent_region_id = region_ref.get('parent_region_id') if parent_region_id is not None: # This will raise NotFound if the parent doesn't exist, # which is the behavior we want. self._get_region(session, parent_region_id) def get_region(self, region_id): session = sql.get_session() return self._get_region(session, region_id).to_dict() def delete_region(self, region_id): session = sql.get_session() with session.begin(): ref = self._get_region(session, region_id) self._delete_child_regions(session, region_id) session.query(Region).filter_by(id=region_id).delete() session.delete(ref) @sql.handle_conflicts(conflict_type='region') def create_region(self, region_ref): session = sql.get_session() with session.begin(): self._check_parent_region(session, region_ref) region = Region.from_dict(region_ref) session.add(region) return region.to_dict() def update_region(self, region_id, region_ref): session = sql.get_session() with session.begin(): self._check_parent_region(session, region_ref) ref = self._get_region(session, region_id) old_dict = ref.to_dict() old_dict.update(region_ref) new_region = Region.from_dict(old_dict) for attr in Region.attributes: if attr != 'id': setattr(ref, attr, getattr(new_region, attr)) return ref.to_dict() # Services @sql.truncated def list_services(self, hints): session = sql.get_session() services = session.query(Service) services = sql.filter_limit_query(Service, services, hints) return [s.to_dict() for s in list(services)] def _get_service(self, session, service_id): ref = session.query(Service).get(service_id) if not ref: raise exception.ServiceNotFound(service_id=service_id) return ref def get_service(self, service_id): session = sql.get_session() return self._get_service(session, service_id).to_dict() def delete_service(self, service_id): session = sql.get_session() with session.begin(): ref = self._get_service(session, service_id) session.query(Endpoint).filter_by(service_id=service_id).delete() session.delete(ref) def create_service(self, service_id, service_ref): session = sql.get_session() with session.begin(): service = Service.from_dict(service_ref) session.add(service) return service.to_dict() def update_service(self, service_id, service_ref): session = sql.get_session() with session.begin(): ref = self._get_service(session, service_id) old_dict = ref.to_dict() old_dict.update(service_ref) new_service = Service.from_dict(old_dict) for attr in Service.attributes: if attr != 'id': setattr(ref, attr, getattr(new_service, attr)) ref.extra = new_service.extra return ref.to_dict() # Endpoints def create_endpoint(self, endpoint_id, endpoint_ref): session = sql.get_session() self.get_service(endpoint_ref['service_id']) new_endpoint = Endpoint.from_dict(endpoint_ref) with session.begin(): session.add(new_endpoint) return new_endpoint.to_dict() def delete_endpoint(self, endpoint_id): session = sql.get_session() with session.begin(): ref = self._get_endpoint(session, endpoint_id) session.delete(ref) def _get_endpoint(self, session, endpoint_id): try: return session.query(Endpoint).filter_by(id=endpoint_id).one() except sql.NotFound: raise exception.EndpointNotFound(endpoint_id=endpoint_id) def get_endpoint(self, endpoint_id): session = sql.get_session() return self._get_endpoint(session, endpoint_id).to_dict() @sql.truncated def list_endpoints(self, hints): session = sql.get_session() endpoints = session.query(Endpoint) endpoints = sql.filter_limit_query(Endpoint, endpoints, hints) return [e.to_dict() for e in list(endpoints)] def update_endpoint(self, endpoint_id, endpoint_ref): session = sql.get_session() with session.begin(): ref = self._get_endpoint(session, endpoint_id) old_dict = ref.to_dict() old_dict.update(endpoint_ref) new_endpoint = Endpoint.from_dict(old_dict) for attr in Endpoint.attributes: if attr != 'id': setattr(ref, attr, getattr(new_endpoint, attr)) ref.extra = new_endpoint.extra return ref.to_dict() def get_catalog(self, user_id, tenant_id, metadata=None): d = dict(six.iteritems(CONF)) d.update({'tenant_id': tenant_id, 'user_id': user_id}) session = sql.get_session() endpoints = (session.query(Endpoint). options(sql.joinedload(Endpoint.service)). filter(Endpoint.enabled == True).all()) # flake8: noqa catalog = {} for endpoint in endpoints: if not endpoint.service['enabled']: continue region = endpoint['region'] service_type = endpoint.service['type'] default_service = { 'id': endpoint['id'], 'name': endpoint.service['name'], 'publicURL': '' } catalog.setdefault(region, {}) catalog[region].setdefault(service_type, default_service) url = core.format_url(endpoint['url'], d) interface_url = '%sURL' % endpoint['interface'] catalog[region][service_type][interface_url] = url return catalog def get_v3_catalog(self, user_id, tenant_id, metadata=None): d = dict(six.iteritems(CONF)) d.update({'tenant_id': tenant_id, 'user_id': user_id}) session = sql.get_session() services = (session.query(Service).filter(Service.enabled == True). options(sql.joinedload(Service.endpoints)). all()) def make_v3_endpoint(endpoint): del endpoint['service_id'] del endpoint['legacy_endpoint_id'] del endpoint['enabled'] endpoint['url'] = core.format_url(endpoint['url'], d) return endpoint catalog = [{'endpoints': [make_v3_endpoint(ep.to_dict()) for ep in svc.endpoints if ep.enabled], 'id': svc.id, 'type': svc.type} for svc in services] return catalog keystone-2014.1/keystone/catalog/backends/templated.py0000664000175400017540000001014612323716267024171 0ustar jenkinsjenkins00000000000000# Copyright 2012 OpenStack Foundationc # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import os.path import six from keystone.catalog.backends import kvs from keystone.catalog import core from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import versionutils LOG = log.getLogger(__name__) CONF = config.CONF def parse_templates(template_lines): o = {} for line in template_lines: if ' = ' not in line: continue k, v = line.strip().split(' = ') if not k.startswith('catalog.'): continue parts = k.split('.') region = parts[1] # NOTE(termie): object-store insists on having a dash service = parts[2].replace('_', '-') key = parts[3] region_ref = o.get(region, {}) service_ref = region_ref.get(service, {}) service_ref[key] = v region_ref[service] = service_ref o[region] = region_ref return o class Catalog(kvs.Catalog): """A backend that generates endpoints for the Catalog based on templates. It is usually configured via config entries that look like: catalog.$REGION.$SERVICE.$key = $value and is stored in a similar looking hierarchy. Where a value can contain values to be interpolated by standard python string interpolation that look like (the % is replaced by a $ due to paste attempting to interpolate on its own: http://localhost:$(public_port)s/ When expanding the template it will pass in a dict made up of the conf instance plus a few additional key-values, notably tenant_id and user_id. It does not care what the keys and values are but it is worth noting that keystone_compat will expect certain keys to be there so that it can munge them into the output format keystone expects. These keys are: name - the name of the service, most likely repeated for all services of the same type, across regions. adminURL - the url of the admin endpoint publicURL - the url of the public endpoint internalURL - the url of the internal endpoint """ def __init__(self, templates=None): super(Catalog, self).__init__() if templates: self.templates = templates else: template_file = CONF.catalog.template_file if not os.path.exists(template_file): template_file = CONF.find_file(template_file) self._load_templates(template_file) def _load_templates(self, template_file): try: self.templates = parse_templates(open(template_file)) except IOError: LOG.critical(_('Unable to open template file %s'), template_file) raise def get_catalog(self, user_id, tenant_id, metadata=None): d = dict(six.iteritems(CONF)) d.update({'tenant_id': tenant_id, 'user_id': user_id}) o = {} for region, region_ref in six.iteritems(self.templates): o[region] = {} for service, service_ref in six.iteritems(region_ref): o[region][service] = {} for k, v in six.iteritems(service_ref): o[region][service][k] = core.format_url(v, d) return o def get_v3_catalog(self, user_id, tenant_id, metadata=None): raise exception.NotImplemented() @versionutils.deprecated( versionutils.deprecated.ICEHOUSE, in_favor_of='keystone.catalog.backends.templated.Catalog', remove_in=+2) class TemplatedCatalog(Catalog): pass keystone-2014.1/keystone/catalog/backends/kvs.py0000664000175400017540000001224212323716267023014 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone import catalog from keystone.common import kvs from keystone import exception class Catalog(kvs.Base, catalog.Driver): # Public interface def get_catalog(self, user_id, tenant_id, metadata=None): return self.db.get('catalog-%s-%s' % (tenant_id, user_id)) # region crud def _delete_child_regions(self, region_id): """Delete all child regions. Recursively delete any region that has the supplied region as its parent. """ children = [r for r in self.list_regions() if r['parent_region_id'] == region_id] for child in children: self._delete_child_regions(child['id']) self.delete_region(child['id']) def _check_parent_region(self, region_ref): """Raise a NotFound if the parent region does not exist. If the region_ref has a specified parent_region_id, check that the parent exists, otherwise, raise a NotFound. """ parent_region_id = region_ref.get('parent_region_id') if parent_region_id is not None: # This will raise NotFound if the parent doesn't exist, # which is the behavior we want. self.get_region(parent_region_id) def create_region(self, region): region_id = region['id'] region.setdefault('parent_region_id') self._check_parent_region(region) self.db.set('region-%s' % region_id, region) region_list = set(self.db.get('region_list', [])) region_list.add(region_id) self.db.set('region_list', list(region_list)) return region def list_regions(self): return [self.get_region(x) for x in self.db.get('region_list', [])] def get_region(self, region_id): return self.db.get('region-%s' % region_id) def update_region(self, region_id, region): region.setdefault('parent_region_id') self._check_parent_region(region) self.db.set('region-%s' % region_id, region) return region def delete_region(self, region_id): self._delete_child_regions(region_id) self.db.delete('region-%s' % region_id) region_list = set(self.db.get('region_list', [])) region_list.remove(region_id) self.db.set('region_list', list(region_list)) # service crud def create_service(self, service_id, service): self.db.set('service-%s' % service_id, service) service_list = set(self.db.get('service_list', [])) service_list.add(service_id) self.db.set('service_list', list(service_list)) return service def list_services(self, hints): return [self.get_service(x) for x in self.db.get('service_list', [])] def get_service(self, service_id): return self.db.get('service-%s' % service_id) def update_service(self, service_id, service): self.db.set('service-%s' % service_id, service) return service def delete_service(self, service_id): # delete referencing endpoints for endpoint_id in self.db.get('endpoint_list', []): if self.get_endpoint(endpoint_id)['service_id'] == service_id: self.delete_endpoint(endpoint_id) self.db.delete('service-%s' % service_id) service_list = set(self.db.get('service_list', [])) service_list.remove(service_id) self.db.set('service_list', list(service_list)) # endpoint crud def create_endpoint(self, endpoint_id, endpoint): self.get_service(endpoint['service_id']) self.db.set('endpoint-%s' % endpoint_id, endpoint) endpoint_list = set(self.db.get('endpoint_list', [])) endpoint_list.add(endpoint_id) self.db.set('endpoint_list', list(endpoint_list)) return endpoint def list_endpoints(self, hints): return [self.get_endpoint(x) for x in self.db.get('endpoint_list', [])] def get_endpoint(self, endpoint_id): return self.db.get('endpoint-%s' % endpoint_id) def update_endpoint(self, endpoint_id, endpoint): self.db.set('endpoint-%s' % endpoint_id, endpoint) return endpoint def delete_endpoint(self, endpoint_id): self.db.delete('endpoint-%s' % endpoint_id) endpoint_list = set(self.db.get('endpoint_list', [])) endpoint_list.remove(endpoint_id) self.db.set('endpoint_list', list(endpoint_list)) # Private interface def _create_catalog(self, user_id, tenant_id, data): self.db.set('catalog-%s-%s' % (tenant_id, user_id), data) return data def get_v3_catalog(self, user_id, tenant_id, metadata=None): raise exception.NotImplemented() keystone-2014.1/keystone/catalog/backends/__init__.py0000664000175400017540000000000012323716267023735 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/catalog/__init__.py0000664000175400017540000000131412323716272022170 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.catalog import controllers from keystone.catalog.core import * from keystone.catalog import routers keystone-2014.1/keystone/config.py0000664000175400017540000000557112323716267020301 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Wrapper for keystone.common.config that configures itself on import.""" import os from keystone.common import config from keystone import exception from keystone.openstack.common import log CONF = config.CONF setup_authentication = config.setup_authentication configure = config.configure def set_default_for_default_log_levels(): """Set the default for the default_log_levels option for keystone. Keystone uses some packages that other OpenStack services don't use that do logging. This will set the default_log_levels default level for those packages. This function needs to be called before CONF(). """ extra_log_level_defaults = [ 'dogpile=INFO', 'routes=INFO', ] def find_default_log_levels_opt(): for opt in log.log_opts: if opt.dest == 'default_log_levels': return opt opt = find_default_log_levels_opt() opt.default.extend(extra_log_level_defaults) def setup_logging(): """Sets up logging for the keystone package.""" log.setup('keystone') def find_paste_config(): """Find Keystone's paste.deploy configuration file. Keystone's paste.deploy configuration file is specified in the ``[paste_deploy]`` section of the main Keystone configuration file, ``keystone.conf``. For example:: [paste_deploy] config_file = keystone-paste.ini :returns: The selected configuration filename :raises: exception.ConfigFileNotFound """ if CONF.paste_deploy.config_file: paste_config = CONF.paste_deploy.config_file paste_config_value = paste_config if not os.path.isabs(paste_config): paste_config = CONF.find_file(paste_config) elif CONF.config_file: paste_config = CONF.config_file[0] paste_config_value = paste_config else: # this provides backwards compatibility for keystone.conf files that # still have the entire paste configuration included, rather than just # a [paste_deploy] configuration section referring to an external file paste_config = CONF.find_file('keystone.conf') paste_config_value = 'keystone.conf' if not paste_config or not os.path.exists(paste_config): raise exception.ConfigFileNotFound(config_file=paste_config_value) return paste_config keystone-2014.1/keystone/service.py0000664000175400017540000001053712323716272020466 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sys import functools import routes from keystone import assignment from keystone import auth from keystone import catalog from keystone.common import cache from keystone.common import wsgi from keystone import config from keystone.contrib import endpoint_filter from keystone import controllers from keystone import credential from keystone import identity from keystone.openstack.common import log from keystone import policy from keystone import routers from keystone import token from keystone import trust CONF = config.CONF LOG = log.getLogger(__name__) def load_backends(): # Configure and build the cache cache.configure_cache_region(cache.REGION) # Ensure that the identity driver is created before the assignment manager. # The default assignment driver is determined by the identity driver, so # the identity driver must be available to the assignment manager. _IDENTITY_API = identity.Manager() DRIVERS = dict( assignment_api=assignment.Manager(), catalog_api=catalog.Manager(), credential_api=credential.Manager(), endpoint_filter_api=endpoint_filter.Manager(), identity_api=_IDENTITY_API, policy_api=policy.Manager(), token_api=token.Manager(), trust_api=trust.Manager(), token_provider_api=token.provider.Manager()) auth.controllers.load_auth_methods() return DRIVERS def fail_gracefully(f): """Logs exceptions and aborts.""" @functools.wraps(f) def wrapper(*args, **kw): try: return f(*args, **kw) except Exception as e: LOG.debug(e, exc_info=True) # exception message is printed to all logs LOG.critical(e) sys.exit(1) return wrapper @fail_gracefully def public_app_factory(global_conf, **local_conf): controllers.register_version('v2.0') conf = global_conf.copy() conf.update(local_conf) return wsgi.ComposingRouter(routes.Mapper(), [assignment.routers.Public(), token.routers.Router(), routers.VersionV2('public'), routers.Extension(False)]) @fail_gracefully def admin_app_factory(global_conf, **local_conf): conf = global_conf.copy() conf.update(local_conf) return wsgi.ComposingRouter(routes.Mapper(), [identity.routers.Admin(), assignment.routers.Admin(), token.routers.Router(), routers.VersionV2('admin'), routers.Extension()]) @fail_gracefully def public_version_app_factory(global_conf, **local_conf): conf = global_conf.copy() conf.update(local_conf) return wsgi.ComposingRouter(routes.Mapper(), [routers.Versions('public')]) @fail_gracefully def admin_version_app_factory(global_conf, **local_conf): conf = global_conf.copy() conf.update(local_conf) return wsgi.ComposingRouter(routes.Mapper(), [routers.Versions('admin')]) @fail_gracefully def v3_app_factory(global_conf, **local_conf): controllers.register_version('v3') conf = global_conf.copy() conf.update(local_conf) mapper = routes.Mapper() v3routers = [] for module in [assignment, auth, catalog, credential, identity, policy]: module.routers.append_v3_routers(mapper, v3routers) if CONF.trust.enabled: trust.routers.append_v3_routers(mapper, v3routers) # Add in the v3 version api v3routers.append(routers.VersionV3('admin')) v3routers.append(routers.VersionV3('public')) # TODO(ayoung): put token routes here return wsgi.ComposingRouter(mapper, v3routers) keystone-2014.1/keystone/contrib/0000775000175400017540000000000012323716511020102 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/stats/0000775000175400017540000000000012323716511021240 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/stats/core.py0000664000175400017540000001214312323716267022553 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import extension from keystone.common import manager from keystone.common import wsgi from keystone import config from keystone import exception from keystone.openstack.common import log from keystone.openstack.common import versionutils CONF = config.CONF LOG = log.getLogger(__name__) extension_data = { 'name': 'OpenStack Keystone Stats API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-STATS/v1.0', 'alias': 'OS-STATS', 'updated': '2013-07-07T12:00:0-00:00', 'description': 'OpenStack Keystone Stats API.', 'links': [ { 'rel': 'describedby', # TODO(ayoung): needs a description 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]} extension.register_admin_extension(extension_data['alias'], extension_data) class Manager(manager.Manager): """Default pivot point for the Stats backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.stats.driver) class Driver(object): """Interface description for a Stats driver.""" def get_stats(self, api): """Retrieve all previously-captured statistics for an interface.""" raise exception.NotImplemented() def set_stats(self, api, stats_ref): """Update statistics for an interface.""" raise exception.NotImplemented() def increment_stat(self, api, category, value): """Increment the counter for an individual statistic.""" raise exception.NotImplemented() class StatsExtension(wsgi.ExtensionRouter): """Reports on previously-collected request/response statistics.""" def add_routes(self, mapper): stats_controller = StatsController() mapper.connect( '/OS-STATS/stats', controller=stats_controller, action='get_stats', conditions=dict(method=['GET'])) mapper.connect( '/OS-STATS/stats', controller=stats_controller, action='reset_stats', conditions=dict(method=['DELETE'])) class StatsController(wsgi.Application): def __init__(self): self.stats_api = Manager() super(StatsController, self).__init__() def get_stats(self, context): self.assert_admin(context) return { 'OS-STATS:stats': [ { 'type': 'identity', 'api': 'admin', 'extra': self.stats_api.get_stats('admin'), }, { 'type': 'identity', 'api': 'public', 'extra': self.stats_api.get_stats('public'), }, ] } def reset_stats(self, context): self.assert_admin(context) self.stats_api.set_stats('public', dict()) self.stats_api.set_stats('admin', dict()) class StatsMiddleware(wsgi.Middleware): """Monitors various request/response attribute statistics.""" request_attributes = ['application_url', 'method', 'path', 'path_qs', 'remote_addr'] response_attributes = ['status_int'] @versionutils.deprecated( what='keystone.contrib.stats.core.StatsMiddleware', as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='external tooling', remove_in=+2) def __init__(self, *args, **kwargs): self.stats_api = Manager() return super(StatsMiddleware, self).__init__(*args, **kwargs) def _resolve_api(self, host): if host.endswith(':%s' % (CONF.admin_port)): return 'admin' elif host.endswith(':%s' % (CONF.public_port)): return 'public' else: return host def capture_stats(self, host, obj, attributes): """Collect each attribute from the given object.""" for attribute in attributes: self.stats_api.increment_stat( self._resolve_api(host), attribute, getattr(obj, attribute)) def process_request(self, request): """Monitor incoming request attributes.""" self.capture_stats(request.host, request, self.request_attributes) def process_response(self, request, response): """Monitor outgoing response attributes.""" self.capture_stats(request.host, response, self.response_attributes) return response keystone-2014.1/keystone/contrib/stats/backends/0000775000175400017540000000000012323716511023012 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/stats/backends/kvs.py0000664000175400017540000000227012323716267024200 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import kvs from keystone.contrib import stats class Stats(kvs.Base, stats.Driver): def get_stats(self, api): return self.db.get('stats-%s' % api, {}) def set_stats(self, api, stats_ref): self.db.set('stats-%s' % api, stats_ref) def increment_stat(self, api, category, value): """Increment a statistic counter, or create it if it doesn't exist.""" stats = self.get_stats(api) stats.setdefault(category, dict()) counter = stats[category].setdefault(value, 0) stats[category][value] = counter + 1 self.set_stats(api, stats) keystone-2014.1/keystone/contrib/stats/backends/__init__.py0000664000175400017540000000000012323716267025121 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/stats/__init__.py0000664000175400017540000000120412323716272023352 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.contrib.stats.core import * keystone-2014.1/keystone/contrib/access/0000775000175400017540000000000012323716511021343 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/access/core.py0000664000175400017540000000461512323716267022663 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import webob.dec from keystone.common import wsgi from keystone import config from keystone.openstack.common import log from keystone.openstack.common import timeutils from keystone.openstack.common import versionutils CONF = config.CONF LOG = log.getLogger('access') APACHE_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S' APACHE_LOG_FORMAT = ( '%(remote_addr)s - %(remote_user)s [%(datetime)s] "%(method)s %(url)s ' '%(http_version)s" %(status)s %(content_length)s') class AccessLogMiddleware(wsgi.Middleware): """Writes an access log to INFO.""" @versionutils.deprecated( what='keystone.contrib.access.core.AccessLogMiddleware', as_of=versionutils.deprecated.ICEHOUSE, in_favor_of='eventlet debug access log or httpd access log', remove_in=+2) def __init__(self, *args, **kwargs): super(AccessLogMiddleware, self).__init__(*args, **kwargs) @webob.dec.wsgify def __call__(self, request): data = { 'remote_addr': request.remote_addr, 'remote_user': request.remote_user or '-', 'method': request.method, 'url': request.url, 'http_version': request.http_version, 'status': 500, 'content_length': '-'} try: response = request.get_response(self.application) data['status'] = response.status_int data['content_length'] = len(response.body) or '-' finally: # must be calculated *after* the application has been called now = timeutils.utcnow() # timeutils may not return UTC, so we can't hardcode +0000 data['datetime'] = '%s %s' % (now.strftime(APACHE_TIME_FORMAT), now.strftime('%z') or '+0000') LOG.info(APACHE_LOG_FORMAT, data) return response keystone-2014.1/keystone/contrib/access/__init__.py0000664000175400017540000000120512323716272023456 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2013 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. from keystone.contrib.access.core import * keystone-2014.1/keystone/contrib/federation/0000775000175400017540000000000012323716511022222 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/controllers.py0000664000175400017540000002643212323716272025155 0ustar jenkinsjenkins00000000000000# 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. """Extensions supporting Federation.""" from keystone.auth import controllers as auth_controllers from keystone.common import authorization from keystone.common import controller from keystone.common import dependency from keystone.common import wsgi from keystone import config from keystone.contrib.federation import utils from keystone import exception CONF = config.CONF class _ControllerBase(controller.V3Controller): """Base behaviors for federation controllers.""" @classmethod def base_url(cls, context, path=None): """Construct a path and pass it to V3Controller.base_url method.""" path = '/OS-FEDERATION/' + cls.collection_name return super(_ControllerBase, cls).base_url(context, path=path) @dependency.requires('federation_api') class IdentityProvider(_ControllerBase): """Identity Provider representation.""" collection_name = 'identity_providers' member_name = 'identity_provider' _mutable_parameters = frozenset(['description', 'enabled']) _public_parameters = frozenset(['id', 'enabled', 'description', 'links']) @classmethod def _add_related_links(cls, context, ref): """Add URLs for entities related with Identity Provider. Add URLs pointing to: - protocols tied to the Identity Provider """ ref.setdefault('links', {}) base_path = ref['links'].get('self') if base_path is None: base_path = '/'.join([IdentityProvider.base_url(context), ref['id']]) for name in ['protocols']: ref['links'][name] = '/'.join([base_path, name]) @classmethod def _add_self_referential_link(cls, context, ref): id = ref.get('id') self_path = '/'.join([cls.base_url(context), id]) ref.setdefault('links', {}) ref['links']['self'] = self_path @classmethod def wrap_member(cls, context, ref): cls._add_self_referential_link(context, ref) cls._add_related_links(context, ref) ref = cls.filter_params(ref) return {cls.member_name: ref} #TODO(marek-denis): Implement, when mapping engine is ready def _delete_tokens_issued_by_idp(self, idp_id): """Delete tokens created upon authentication from an IdP After the IdP is deregistered, users authenticating via such IdP should no longer be allowed to use federated services. Thus, delete all the tokens issued upon authentication from IdP with idp_id id :param idp_id: id of Identity Provider for which related tokens should be removed. """ raise exception.NotImplemented() @controller.protected() def create_identity_provider(self, context, idp_id, identity_provider): identity_provider = self._normalize_dict(identity_provider) identity_provider.setdefault('enabled', False) IdentityProvider.check_immutable_params(identity_provider) idp_ref = self.federation_api.create_idp(idp_id, identity_provider) response = IdentityProvider.wrap_member(context, idp_ref) return wsgi.render_response(body=response, status=('201', 'Created')) @controller.protected() def list_identity_providers(self, context): ref = self.federation_api.list_idps() ref = [self.filter_params(x) for x in ref] return IdentityProvider.wrap_collection(context, ref) @controller.protected() def get_identity_provider(self, context, idp_id): ref = self.federation_api.get_idp(idp_id) return IdentityProvider.wrap_member(context, ref) @controller.protected() def delete_identity_provider(self, context, idp_id): self.federation_api.delete_idp(idp_id) @controller.protected() def update_identity_provider(self, context, idp_id, identity_provider): identity_provider = self._normalize_dict(identity_provider) IdentityProvider.check_immutable_params(identity_provider) idp_ref = self.federation_api.update_idp(idp_id, identity_provider) return IdentityProvider.wrap_member(context, idp_ref) @dependency.requires('federation_api') class FederationProtocol(_ControllerBase): """A federation protocol representation. See IdentityProvider docstring for explanation on _mutable_parameters and _public_parameters class attributes. """ collection_name = 'protocols' member_name = 'protocol' _public_parameters = frozenset(['id', 'mapping_id', 'links']) _mutable_parameters = frozenset(['mapping_id']) @classmethod def _add_self_referential_link(cls, context, ref): """Add 'links' entry to the response dictionary. Calls IdentityProvider.base_url() class method, as it constructs proper URL along with the 'identity providers' part included. :param ref: response dictionary """ ref.setdefault('links', {}) base_path = ref['links'].get('identity_provider') if base_path is None: base_path = [IdentityProvider.base_url(context), ref['idp_id']] base_path = '/'.join(base_path) self_path = [base_path, 'protocols', ref['id']] self_path = '/'.join(self_path) ref['links']['self'] = self_path @classmethod def _add_related_links(cls, context, ref): """Add new entries to the 'links' subdictionary in the response. Adds 'identity_provider' key with URL pointing to related identity provider as a value. :param ref: response dictionary """ ref.setdefault('links', {}) base_path = '/'.join([IdentityProvider.base_url(context), ref['idp_id']]) ref['links']['identity_provider'] = base_path @classmethod def wrap_member(cls, context, ref): cls._add_related_links(context, ref) cls._add_self_referential_link(context, ref) ref = cls.filter_params(ref) return {cls.member_name: ref} @controller.protected() def create_protocol(self, context, idp_id, protocol_id, protocol): ref = self._normalize_dict(protocol) FederationProtocol.check_immutable_params(ref) ref = self.federation_api.create_protocol(idp_id, protocol_id, ref) response = FederationProtocol.wrap_member(context, ref) return wsgi.render_response(body=response, status=('201', 'Created')) @controller.protected() def update_protocol(self, context, idp_id, protocol_id, protocol): ref = self._normalize_dict(protocol) FederationProtocol.check_immutable_params(ref) ref = self.federation_api.update_protocol(idp_id, protocol_id, protocol) return FederationProtocol.wrap_member(context, ref) @controller.protected() def get_protocol(self, context, idp_id, protocol_id): ref = self.federation_api.get_protocol(idp_id, protocol_id) return FederationProtocol.wrap_member(context, ref) @controller.protected() def list_protocols(self, context, idp_id): protocols_ref = self.federation_api.list_protocols(idp_id) protocols = list(protocols_ref) return FederationProtocol.wrap_collection(context, protocols) @controller.protected() def delete_protocol(self, context, idp_id, protocol_id): self.federation_api.delete_protocol(idp_id, protocol_id) @dependency.requires('federation_api') class MappingController(_ControllerBase): collection_name = 'mappings' member_name = 'mapping' @controller.protected() def create_mapping(self, context, mapping_id, mapping): ref = self._normalize_dict(mapping) utils.validate_mapping_structure(ref) mapping_ref = self.federation_api.create_mapping(mapping_id, ref) response = MappingController.wrap_member(context, mapping_ref) return wsgi.render_response(body=response, status=('201', 'Created')) @controller.protected() def list_mappings(self, context): ref = self.federation_api.list_mappings() return MappingController.wrap_collection(context, ref) @controller.protected() def get_mapping(self, context, mapping_id): ref = self.federation_api.get_mapping(mapping_id) return MappingController.wrap_member(context, ref) @controller.protected() def delete_mapping(self, context, mapping_id): self.federation_api.delete_mapping(mapping_id) @controller.protected() def update_mapping(self, context, mapping_id, mapping): mapping = self._normalize_dict(mapping) utils.validate_mapping_structure(mapping) mapping_ref = self.federation_api.update_mapping(mapping_id, mapping) return MappingController.wrap_member(context, mapping_ref) class Auth(auth_controllers.Auth): def federated_authentication(self, context, identity_provider, protocol): """Authenticate from dedicated url endpoint. Build HTTP request body for federated authentication and inject it into the ``authenticate_for_token`` function. """ auth = { 'identity': { 'methods': ['saml2'], 'saml2': { 'identity_provider': identity_provider, 'protocol': protocol } } } return self.authenticate_for_token(context, auth=auth) @dependency.requires('assignment_api') class DomainV3(controller.V3Controller): collection_name = 'domains' member_name = 'domain' def __init__(self): super(DomainV3, self).__init__() self.get_member_from_driver = self.assignment_api.get_domain @controller.protected() def list_domains_for_groups(self, context): """List all domains available to an authenticated user's groups. :param context: request context :returns: list of accessible domains """ auth_context = context['environment'][authorization.AUTH_CONTEXT_ENV] domains = self.assignment_api.list_domains_for_groups( auth_context['group_ids']) return DomainV3.wrap_collection(context, domains) @dependency.requires('assignment_api') class ProjectV3(controller.V3Controller): collection_name = 'projects' member_name = 'project' def __init__(self): super(ProjectV3, self).__init__() self.get_member_from_driver = self.assignment_api.get_project @controller.protected() def list_projects_for_groups(self, context): """List all projects available to an authenticated user's groups. :param context: request context :returns: list of accessible projects """ auth_context = context['environment'][authorization.AUTH_CONTEXT_ENV] projects = self.assignment_api.list_projects_for_groups( auth_context['group_ids']) return ProjectV3.wrap_collection(context, projects) keystone-2014.1/keystone/contrib/federation/utils.py0000664000175400017540000003106212323716272023742 0ustar jenkinsjenkins00000000000000# 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. """Utilities for Federation Extension.""" import re import jsonschema import six from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log LOG = log.getLogger(__name__) MAPPING_SCHEMA = { "type": "object", "required": ['rules'], "properties": { "rules": { "minItems": 1, "type": "array", "items": { "type": "object", "required": ['local', 'remote'], "additionalProperties": False, "properties": { "local": { "type": "array" }, "remote": { "minItems": 1, "type": "array", "items": { "type": "object", "oneOf": [ {"$ref": "#/definitions/empty"}, {"$ref": "#/definitions/any_one_of"}, {"$ref": "#/definitions/not_any_of"} ], } } } } } }, "definitions": { "empty": { "type": "object", "required": ['type'], "properties": { "type": { "type": "string" }, }, "additionalProperties": False, }, "any_one_of": { "type": "object", "additionalProperties": False, "required": ['type', 'any_one_of'], "properties": { "type": { "type": "string" }, "any_one_of": { "type": "array" }, "regex": { "type": "boolean" } } }, "not_any_of": { "type": "object", "additionalProperties": False, "required": ['type', 'not_any_of'], "properties": { "type": { "type": "string" }, "not_any_of": { "type": "array" }, "regex": { "type": "boolean" } } } } } def validate_mapping_structure(ref): v = jsonschema.Draft4Validator(MAPPING_SCHEMA) messages = '' for error in sorted(v.iter_errors(ref), key=str): messages = messages + error.message + "\n" if messages: raise exception.ValidationError(messages) class RuleProcessor(object): """A class to process assertions and mapping rules.""" class _EvalType(object): """Mapping rule evaluation types.""" ANY_ONE_OF = 'any_one_of' NOT_ANY_OF = 'not_any_of' def __init__(self, rules): """Initialize RuleProcessor. Example rules can be found at: :class:`keystone.tests.mapping_fixtures` :param rules: rules from a mapping :type rules: dict """ self.rules = rules def process(self, assertion_data): """Transform assertion to a dictionary of user name and group ids based on mapping rules. This function will iterate through the mapping rules to find assertions that are valid. :param assertion_data: an assertion containing values from an IdP :type assertion_data: dict Example assertion_data:: { 'Email': 'testacct@example.com', 'UserName': 'testacct', 'FirstName': 'Test', 'LastName': 'Account', 'orgPersonType': 'Tester' } :returns: dictionary with user and group_ids The expected return structure is:: { 'name': 'foobar', 'group_ids': ['abc123', 'def456'] } """ # Assertions will come in as string key-value pairs, and will use a # semi-colon to indicate multiple values, i.e. groups. # This will create a new dictionary where the values are arrays, and # any multiple values are stored in the arrays. assertion = dict((n, v.split(';')) for n, v in assertion_data.items() if isinstance(v, six.string_types)) identity_values = [] for rule in self.rules: direct_maps = self._verify_all_requirements(rule['remote'], assertion) # If the compare comes back as None, then the rule did not apply # to the assertion data, go on to the next rule if direct_maps is None: continue # If there are no direct mappings, then add the local mapping # directly to the array of saved values. However, if there is # a direct mapping, then perform variable replacement. if not direct_maps: identity_values += rule['local'] else: for local in rule['local']: new_local = self._update_local_mapping(local, direct_maps) identity_values.append(new_local) mapped_properties = self._transform(identity_values) if mapped_properties.get('name') is None: raise exception.Unauthorized(_("Could not map user")) return mapped_properties def _transform(self, identity_values): """Transform local mappings, to an easier to understand format. Transform the incoming array to generate the return value for the process function. Generating content for Keystone tokens will be easier if some pre-processing is done at this level. :param identity_values: local mapping from valid evaluations :type identity_values: array of dict Example identity_values:: [{'group': {'id': '0cd5e9'}, 'user': {'email': 'bob@example.com'}}] :returns: dictionary with user name and group_ids. """ # initialize the group_ids as a set to eliminate duplicates user_name = None group_ids = set() for identity_value in identity_values: if 'user' in identity_value: # if a mapping outputs more than one user name, log it if user_name is not None: LOG.warning(_('Ignoring user name %s'), identity_value['user']['name']) else: user_name = identity_value['user']['name'] if 'group' in identity_value: group_ids.add(identity_value['group']['id']) return {'name': user_name, 'group_ids': list(group_ids)} def _update_local_mapping(self, local, direct_maps): """Replace any {0}, {1} ... values with data from the assertion. :param local: local mapping reference that needs to be updated :type local: dict :param direct_maps: list of identity values, used to update local :type direct_maps: list Example local:: {'user': {'name': '{0} {1}', 'email': '{2}'}} Example direct_maps:: ['Bob', 'Thompson', 'bob@example.com'] :returns: new local mapping reference with replaced values. The expected return structure is:: {'user': {'name': 'Bob Thompson', 'email': 'bob@example.org'}} """ new = {} for k, v in six.iteritems(local): if isinstance(v, dict): new_value = self._update_local_mapping(v, direct_maps) else: new_value = v.format(*direct_maps) new[k] = new_value return new def _verify_all_requirements(self, requirements, assertion): """Go through the remote requirements of a rule, and compare against the assertion. If a value of ``None`` is returned, the rule with this assertion doesn't apply. If an array of zero length is returned, then there are no direct mappings to be performed, but the rule is valid. Otherwise, then it will return the values, in order, to be directly mapped, again, the rule is valid. :param requirements: list of remote requirements from rules :type requirements: list Example requirements:: [ { "type": "UserName" }, { "type": "orgPersonType", "any_one_of": [ "Customer" ] } ] :param assertion: dict of attributes from an IdP :type assertion: dict Example assertion:: { 'UserName': ['testacct'], 'LastName': ['Account'], 'orgPersonType': ['Tester'], 'Email': ['testacct@example.com'], 'FirstName': ['Test'] } :returns: list of direct mappings or None. """ direct_maps = [] for requirement in requirements: requirement_type = requirement['type'] regex = requirement.get('regex', False) any_one_values = requirement.get(self._EvalType.ANY_ONE_OF) if any_one_values is not None: if self._evaluate_requirement(any_one_values, requirement_type, self._EvalType.ANY_ONE_OF, regex, assertion): continue else: return None not_any_values = requirement.get(self._EvalType.NOT_ANY_OF) if not_any_values is not None: if self._evaluate_requirement(not_any_values, requirement_type, self._EvalType.NOT_ANY_OF, regex, assertion): continue else: return None # If 'any_one_of' or 'not_any_of' are not found, then values are # within 'type'. Attempt to find that 'type' within the assertion. direct_map_values = assertion.get(requirement_type) if direct_map_values: direct_maps += direct_map_values return direct_maps def _evaluate_requirement(self, values, requirement_type, eval_type, regex, assertion): """Evaluate the incoming requirement and assertion. If the requirement type does not exist in the assertion data, then return False. If regex is specified, then compare the values and assertion values. Otherwise, grab the intersection of the values and use that to compare against the evaluation type. :param values: list of allowed values, defined in the requirement :type values: list :param requirement_type: key to look for in the assertion :type requirement_type: string :param eval_type: determine how to evaluate requirements :type eval_type: string :param regex: perform evaluation with regex :type regex: boolean :param assertion: dict of attributes from the IdP :type assertion: dict :returns: boolean, whether requirement is valid or not. """ assertion_values = assertion.get(requirement_type) if not assertion_values: return False if regex: return re.search(values[0], assertion_values[0]) any_match = bool(set(values).intersection(set(assertion_values))) if any_match and eval_type == self._EvalType.ANY_ONE_OF: return True if not any_match and eval_type == self._EvalType.NOT_ANY_OF: return True return False keystone-2014.1/keystone/contrib/federation/core.py0000664000175400017540000001370212323716267023537 0ustar jenkinsjenkins00000000000000# 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. """Extension supporting Federation.""" import abc import six from keystone.common import dependency from keystone.common import extension from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common import log as logging CONF = config.CONF LOG = logging.getLogger(__name__) EXTENSION_DATA = { 'name': 'OpenStack Federation APIs', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-FEDERATION/v1.0', 'alias': 'OS-FEDERATION', 'updated': '2013-12-17T12:00:0-00:00', 'description': 'OpenStack Identity Providers Mechanism.', 'links': [{ 'rel': 'describedby', 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api' }]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) FEDERATION = 'OS-FEDERATION' IDENTITY_PROVIDER = 'OS-FEDERATION:identity_provider' PROTOCOL = 'OS-FEDERATION:protocol' @dependency.provider('federation_api') class Manager(manager.Manager): """Default pivot point for the Federation backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.federation.driver) @six.add_metaclass(abc.ABCMeta) class Driver(object): def create_idp(self, idp_id, idp): """Create an identity provider. :returns: idp_ref """ raise exception.NotImplemented() def delete_idp(self, idp_id): """Delete an identity provider. :raises: keystone.exception.IdentityProviderNotFound """ raise exception.NotImplemented() def list_idps(self): """List all identity providers. :raises: keystone.exception.IdentityProviderNotFound """ raise exception.NotImplemented() def get_idp(self, idp_id): """Get an identity provider by ID. :raises: keystone.exception.IdentityProviderNotFound """ raise exception.NotImplemented() def update_idp(self, idp_id, idp): """Update an identity provider by ID. :raises: keystone.exception.IdentityProviderNotFound """ raise exception.NotImplemented() def create_protocol(self, idp_id, protocol_id, protocol): """Add an IdP-Protocol configuration. :raises: keystone.exception.IdentityProviderNotFound """ raise exception.NotImplemented() def update_protocol(self, idp_id, protocol_id, protocol): """Change an IdP-Protocol configuration. :raises: keystone.exception.IdentityProviderNotFound, keystone.exception.FederatedProtocolNotFound """ raise exception.NotImplemented() def get_protocol(self, idp_id, protocol_id): """Get an IdP-Protocol configuration. :raises: keystone.exception.IdentityProviderNotFound, keystone.exception.FederatedProtocolNotFound """ raise exception.NotImplemented() def list_protocols(self, idp_id): """List an IdP's supported protocols. :raises: keystone.exception.IdentityProviderNotFound, """ raise exception.NotImplemented() def delete_protocol(self, idp_id, protocol_id): """Delete an IdP-Protocol configuration. :raises: keystone.exception.IdentityProviderNotFound, keystone.exception.FederatedProtocolNotFound, """ raise exception.NotImplemented() @abc.abstractmethod def create_mapping(self, mapping_ref): """Create a mapping. :param mapping_ref: mapping ref with mapping name :type mapping_ref: dict :returns: mapping_ref """ raise exception.NotImplemented() @abc.abstractmethod def delete_mapping(self, mapping_id): """Delete a mapping. :param mapping_id: id of mapping to delete :type mapping_ref: string :returns: None """ raise exception.NotImplemented() @abc.abstractmethod def update_mapping(self, mapping_id, mapping_ref): """Update a mapping. :param mapping_id: id of mapping to update :type mapping_id: string :param mapping_ref: new mapping ref :type mapping_ref: dict :returns: mapping_ref """ raise exception.NotImplemented() @abc.abstractmethod def list_mappings(self): """List all mappings. returns: list of mappings """ raise exception.NotImplemented() @abc.abstractmethod def get_mapping(self, mapping_id): """Get a mapping, returns the mapping based on mapping_id. :param mapping_id: id of mapping to get :type mapping_ref: string :returns: mapping_ref """ raise exception.NotImplemented() @abc.abstractmethod def get_mapping_from_idp_and_protocol(self, idp_id, protocol_id): """Get mapping based on idp_id and protocol_id. :param idp_id: id of the identity provider :type idp_id: string :param protocol_id: id of the protocol :type protocol_id: string :raises: keystone.exception.IdentityProviderNotFound, keystone.exception.FederatedProtocolNotFound, :returns: mapping_ref """ raise exception.NotImplemented() keystone-2014.1/keystone/contrib/federation/routers.py0000664000175400017540000001561412323716267024316 0ustar jenkinsjenkins00000000000000# 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 keystone.common import wsgi from keystone.contrib import federation from keystone.contrib.federation import controllers class FederationExtension(wsgi.ExtensionRouter): """API Endpoints for the Federation extension. The API looks like:: PUT /OS-FEDERATION/identity_providers/$identity_provider GET /OS-FEDERATION/identity_providers GET /OS-FEDERATION/identity_providers/$identity_provider DELETE /OS-FEDERATION/identity_providers/$identity_provider PATCH /OS-FEDERATION/identity_providers/$identity_provider PUT /OS-FEDERATION/identity_providers/ $identity_provider/protocols/$protocol GET /OS-FEDERATION/identity_providers/ $identity_provider/protocols GET /OS-FEDERATION/identity_providers/ $identity_provider/protocols/$protocol PATCH /OS-FEDERATION/identity_providers/ $identity_provider/protocols/$protocol DELETE /OS-FEDERATION/identity_providers/ $identity_provider/protocols/$protocol PUT /OS-FEDERATION/mappings GET /OS-FEDERATION/mappings PATCH /OS-FEDERATION/mappings/$mapping_id GET /OS-FEDERATION/mappings/$mapping_id DELETE /OS-FEDERATION/mappings/$mapping_id GET /OS-FEDERATION/projects GET /OS-FEDERATION/domains GET /OS-FEDERATION/identity_providers/$identity_provider/ protocols/$protocol/auth POST /OS-FEDERATION/identity_providers/$identity_provider/ protocols/$protocol/auth """ def _construct_url(self, suffix): return "/OS-FEDERATION/%s" % suffix def add_routes(self, mapper): # This is needed for dependency injection # it loads the Federation driver which registers it as a dependency. federation.Manager() auth_controller = controllers.Auth() idp_controller = controllers.IdentityProvider() protocol_controller = controllers.FederationProtocol() mapping_controller = controllers.MappingController() project_controller = controllers.ProjectV3() domain_controller = controllers.DomainV3() # Identity Provider CRUD operations mapper.connect( self._construct_url('identity_providers/{idp_id}'), controller=idp_controller, action='create_identity_provider', conditions=dict(method=['PUT'])) mapper.connect( self._construct_url('identity_providers'), controller=idp_controller, action='list_identity_providers', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('identity_providers/{idp_id}'), controller=idp_controller, action='get_identity_provider', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('identity_providers/{idp_id}'), controller=idp_controller, action='delete_identity_provider', conditions=dict(method=['DELETE'])) mapper.connect( self._construct_url('identity_providers/{idp_id}'), controller=idp_controller, action='update_identity_provider', conditions=dict(method=['PATCH'])) # Protocol CRUD operations mapper.connect( self._construct_url('identity_providers/{idp_id}/' 'protocols/{protocol_id}'), controller=protocol_controller, action='create_protocol', conditions=dict(method=['PUT'])) mapper.connect( self._construct_url('identity_providers/{idp_id}/' 'protocols/{protocol_id}'), controller=protocol_controller, action='update_protocol', conditions=dict(method=['PATCH'])) mapper.connect( self._construct_url('identity_providers/{idp_id}/' 'protocols/{protocol_id}'), controller=protocol_controller, action='get_protocol', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('identity_providers/{idp_id}/' 'protocols'), controller=protocol_controller, action='list_protocols', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('identity_providers/{idp_id}/' 'protocols/{protocol_id}'), controller=protocol_controller, action='delete_protocol', conditions=dict(method=['DELETE'])) # Mapping CRUD operations mapper.connect( self._construct_url('mappings/{mapping_id}'), controller=mapping_controller, action='create_mapping', conditions=dict(method=['PUT'])) mapper.connect( self._construct_url('mappings'), controller=mapping_controller, action='list_mappings', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('mappings/{mapping_id}'), controller=mapping_controller, action='get_mapping', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('mappings/{mapping_id}'), controller=mapping_controller, action='delete_mapping', conditions=dict(method=['DELETE'])) mapper.connect( self._construct_url('mappings/{mapping_id}'), controller=mapping_controller, action='update_mapping', conditions=dict(method=['PATCH'])) mapper.connect( self._construct_url('domains'), controller=domain_controller, action='list_domains_for_groups', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('projects'), controller=project_controller, action='list_projects_for_groups', conditions=dict(method=['GET'])) mapper.connect( self._construct_url('identity_providers/' '{identity_provider}/protocols/' '{protocol}/auth'), controller=auth_controller, action='federated_authentication', conditions=dict(method=['GET', 'POST'])) keystone-2014.1/keystone/contrib/federation/backends/0000775000175400017540000000000012323716511023774 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/backends/sql.py0000664000175400017540000002247312323716272025161 0ustar jenkinsjenkins00000000000000# 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. from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.contrib import federation from keystone.contrib.federation import core from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common import jsonutils class FederationProtocolModel(sql.ModelBase, sql.DictBase): __tablename__ = 'federation_protocol' attributes = ['id', 'idp_id', 'mapping_id'] mutable_attributes = frozenset(['mapping_id']) id = sql.Column(sql.String(64), primary_key=True) idp_id = sql.Column(sql.String(64), sql.ForeignKey('identity_provider.id', ondelete='CASCADE'), primary_key=True) mapping_id = sql.Column(sql.String(64), nullable=False) __table_args__ = (sql.UniqueConstraint('id', 'idp_id'), dict()) @classmethod def from_dict(cls, dictionary): new_dictionary = dictionary.copy() return cls(**new_dictionary) def to_dict(self): """Return a dictionary with model's attributes.""" d = dict() for attr in self.__class__.attributes: d[attr] = getattr(self, attr) return d class IdentityProviderModel(sql.ModelBase, sql.DictBase): __tablename__ = 'identity_provider' attributes = ['id', 'enabled', 'description'] mutable_attributes = frozenset(['description', 'enabled']) id = sql.Column(sql.String(64), primary_key=True) enabled = sql.Column(sql.Boolean, nullable=False) description = sql.Column(sql.Text(), nullable=True) @classmethod def from_dict(cls, dictionary): new_dictionary = dictionary.copy() return cls(**new_dictionary) def to_dict(self, include_extra_dict=False): """Return the model's attributes as a dictionary.""" d = dict() for attr in self.__class__.attributes: d[attr] = getattr(self, attr) return d class MappingModel(sql.ModelBase, sql.DictBase): __tablename__ = 'mapping' attributes = ['id', 'rules'] id = sql.Column(sql.String(64), primary_key=True) rules = sql.Column(sql.JsonBlob(), nullable=False) @classmethod def from_dict(cls, dictionary): new_dictionary = dictionary.copy() return cls(**new_dictionary) def to_dict(self): """Return a dictionary with model's attributes.""" d = dict() for attr in self.__class__.attributes: d[attr] = getattr(self, attr) return d class Federation(core.Driver): def db_sync(self): abs_path = migration_helpers.find_migrate_repo(federation) migration.db_sync(sql.get_engine(), abs_path) # Identity Provider CRUD @sql.handle_conflicts(conflict_type='identity_provider') def create_idp(self, idp_id, idp): session = sql.get_session() with session.begin(): idp['id'] = idp_id idp_ref = IdentityProviderModel.from_dict(idp) session.add(idp_ref) return idp_ref.to_dict() def delete_idp(self, idp_id): session = sql.get_session() with session.begin(): idp_ref = self._get_idp(session, idp_id) q = session.query(IdentityProviderModel) q = q.filter_by(id=idp_id) q.delete(synchronize_session=False) session.delete(idp_ref) def _get_idp(self, session, idp_id): idp_ref = session.query(IdentityProviderModel).get(idp_id) if not idp_ref: raise exception.IdentityProviderNotFound(idp_id=idp_id) return idp_ref def list_idps(self): session = sql.get_session() with session.begin(): idps = session.query(IdentityProviderModel) idps_list = [idp.to_dict() for idp in idps] return idps_list def get_idp(self, idp_id): session = sql.get_session() idp_ref = self._get_idp(session, idp_id) return idp_ref.to_dict() def update_idp(self, idp_id, idp): session = sql.get_session() with session.begin(): idp_ref = self._get_idp(session, idp_id) old_idp = idp_ref.to_dict() old_idp.update(idp) new_idp = IdentityProviderModel.from_dict(old_idp) for attr in IdentityProviderModel.mutable_attributes: setattr(idp_ref, attr, getattr(new_idp, attr)) return idp_ref.to_dict() # Protocol CRUD def _get_protocol(self, session, idp_id, protocol_id): q = session.query(FederationProtocolModel) q = q.filter_by(id=protocol_id, idp_id=idp_id) try: return q.one() except sql.NotFound: kwargs = {'protocol_id': protocol_id, 'idp_id': idp_id} raise exception.FederatedProtocolNotFound(**kwargs) @sql.handle_conflicts(conflict_type='federation_protocol') def create_protocol(self, idp_id, protocol_id, protocol): session = sql.get_session() with session.begin(): self._get_idp(session, idp_id) protocol['id'] = protocol_id protocol['idp_id'] = idp_id protocol_ref = FederationProtocolModel.from_dict(protocol) session.add(protocol_ref) return protocol_ref.to_dict() def update_protocol(self, idp_id, protocol_id, protocol): session = sql.get_session() with session.begin(): proto_ref = self._get_protocol(session, idp_id, protocol_id) old_proto = proto_ref.to_dict() old_proto.update(protocol) new_proto = FederationProtocolModel.from_dict(old_proto) for attr in FederationProtocolModel.mutable_attributes: setattr(proto_ref, attr, getattr(new_proto, attr)) return proto_ref.to_dict() def get_protocol(self, idp_id, protocol_id): session = sql.get_session() protocol_ref = self._get_protocol(session, idp_id, protocol_id) return protocol_ref.to_dict() def list_protocols(self, idp_id): session = sql.get_session() q = session.query(FederationProtocolModel) q = q.filter_by(idp_id=idp_id) protocols = [protocol.to_dict() for protocol in q] return protocols def delete_protocol(self, idp_id, protocol_id): session = sql.get_session() with session.begin(): key_ref = self._get_protocol(session, idp_id, protocol_id) q = session.query(FederationProtocolModel) q = q.filter_by(id=protocol_id, idp_id=idp_id) q.delete(synchronize_session=False) session.delete(key_ref) # Mapping CRUD def _get_mapping(self, session, mapping_id): mapping_ref = session.query(MappingModel).get(mapping_id) if not mapping_ref: raise exception.MappingNotFound(mapping_id=mapping_id) return mapping_ref @sql.handle_conflicts(conflict_type='mapping') def create_mapping(self, mapping_id, mapping): session = sql.get_session() ref = {} ref['id'] = mapping_id ref['rules'] = jsonutils.dumps(mapping.get('rules')) with session.begin(): mapping_ref = MappingModel.from_dict(ref) session.add(mapping_ref) return mapping_ref.to_dict() def delete_mapping(self, mapping_id): session = sql.get_session() with session.begin(): mapping_ref = self._get_mapping(session, mapping_id) session.delete(mapping_ref) def list_mappings(self): session = sql.get_session() with session.begin(): mappings = session.query(MappingModel) return [x.to_dict() for x in mappings] def get_mapping(self, mapping_id): session = sql.get_session() with session.begin(): mapping_ref = self._get_mapping(session, mapping_id) return mapping_ref.to_dict() @sql.handle_conflicts(conflict_type='mapping') def update_mapping(self, mapping_id, mapping): ref = {} ref['id'] = mapping_id ref['rules'] = jsonutils.dumps(mapping.get('rules')) session = sql.get_session() with session.begin(): mapping_ref = self._get_mapping(session, mapping_id) old_mapping = mapping_ref.to_dict() old_mapping.update(ref) new_mapping = MappingModel.from_dict(old_mapping) for attr in MappingModel.attributes: setattr(mapping_ref, attr, getattr(new_mapping, attr)) return mapping_ref.to_dict() def get_mapping_from_idp_and_protocol(self, idp_id, protocol_id): session = sql.get_session() with session.begin(): protocol_ref = self._get_protocol(session, idp_id, protocol_id) mapping_id = protocol_ref.mapping_id mapping_ref = self._get_mapping(session, mapping_id) return mapping_ref.to_dict() keystone-2014.1/keystone/contrib/federation/backends/__init__.py0000664000175400017540000000000012323716267026103 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/migrate_repo/0000775000175400017540000000000012323716511024677 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/migrate_repo/versions/0000775000175400017540000000000012323716511026547 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py0000664000175400017540000000321012323716267035227 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine idp_table = sql.Table( 'identity_provider', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('enabled', sql.Boolean, nullable=False), sql.Column('description', sql.Text(), nullable=True)) idp_table.create(migrate_engine, checkfirst=True) federation_protocol_table = sql.Table( 'federation_protocol', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('idp_id', sql.String(64), sql.ForeignKey('identity_provider.id', ondelete='CASCADE'), primary_key=True), sql.Column('mapping_id', sql.String(64), nullable=True)) federation_protocol_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine tables = ['identity_provider', 'federation_protocol'] for table_name in tables: table = sql.Table(table_name, meta, autoload=True) table.drop() keystone-2014.1/keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py0000664000175400017540000000221112323716267033303 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine mapping_table = sql.Table( 'mapping', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('rules', sql.Text(), nullable=False)) mapping_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine # Drop previously created tables tables = ['mapping'] for table_name in tables: table = sql.Table(table_name, meta, autoload=True) table.drop() keystone-2014.1/keystone/contrib/federation/migrate_repo/versions/__init__.py0000664000175400017540000000000012323716267030656 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/migrate_repo/migrate.cfg0000664000175400017540000000231612323716267027022 0ustar jenkinsjenkins00000000000000[db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. repository_id=federation # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. # If this is changed once a database is under version control, you'll need to # change the table name in each database too. version_table=migrate_version # When committing a change script, Migrate will attempt to generate the # sql for all supported databases; normally, if one of them fails - probably # because you don't have that database installed - it is ignored and the # commit continues, perhaps ending successfully. # Databases in this list MUST compile successfully during a commit, or the # entire commit will fail. List the databases your application will actually # be using to ensure your updates to that database work properly. # This must be a list; example: ['postgres','sqlite'] required_dbs=[] # When creating new change scripts, Migrate will stamp the new script with # a version number. By default this is latest_version + 1. You can set this # to 'true' to tell Migrate to use the UTC timestamp instead. use_timestamp_numbering=False keystone-2014.1/keystone/contrib/federation/migrate_repo/__init__.py0000664000175400017540000000000012323716267027006 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/federation/__init__.py0000664000175400017540000000121012323716272024331 0ustar jenkinsjenkins00000000000000# 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. from keystone.contrib.federation.core import * # flake8: noqa keystone-2014.1/keystone/contrib/user_crud/0000775000175400017540000000000012323716511022075 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/user_crud/core.py0000664000175400017540000000676212323716267023422 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import copy import uuid from keystone.common import extension from keystone.common import wsgi from keystone import exception from keystone import identity from keystone.openstack.common import log LOG = log.getLogger(__name__) extension.register_public_extension( 'OS-KSCRUD', { 'name': 'OpenStack Keystone User CRUD', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-KSCRUD/v1.0', 'alias': 'OS-KSCRUD', 'updated': '2013-07-07T12:00:0-00:00', 'description': 'OpenStack extensions to Keystone v2.0 API ' 'enabling User Operations.', 'links': [ { 'rel': 'describedby', # TODO(ayoung): needs a description 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]}) class UserController(identity.controllers.User): def set_user_password(self, context, user_id, user): token_id = context.get('token_id') original_password = user.get('original_password') token_ref = self.token_api.get_token(token_id) user_id_from_token = token_ref['user']['id'] if user_id_from_token != user_id: raise exception.Forbidden('Token belongs to another user') if original_password is None: raise exception.ValidationError(target='user', attribute='original password') try: user_ref = self.identity_api.authenticate( context, user_id=user_id_from_token, password=original_password) if not user_ref.get('enabled', True): # NOTE(dolph): why can't you set a disabled user's password? raise exception.Unauthorized('User is disabled') except AssertionError: raise exception.Unauthorized() update_dict = {'password': user['password'], 'id': user_id} admin_context = copy.copy(context) admin_context['is_admin'] = True super(UserController, self).set_user_password(admin_context, user_id, update_dict) token_id = uuid.uuid4().hex new_token_ref = copy.copy(token_ref) new_token_ref['id'] = token_id self.token_api.create_token(token_id, new_token_ref) LOG.debug('TOKEN_REF %s', new_token_ref) return {'access': {'token': new_token_ref}} class CrudExtension(wsgi.ExtensionRouter): """Provides a subset of CRUD operations for internal data types.""" def add_routes(self, mapper): user_controller = UserController() mapper.connect('/OS-KSCRUD/users/{user_id}', controller=user_controller, action='set_user_password', conditions=dict(method=['PATCH'])) keystone-2014.1/keystone/contrib/user_crud/__init__.py0000664000175400017540000000120012323716272024203 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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 keystone.contrib.user_crud.core import * keystone-2014.1/keystone/contrib/endpoint_filter/0000775000175400017540000000000012323716511023267 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/controllers.py0000664000175400017540000000722012323716267026220 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone import assignment from keystone.catalog import controllers as catalog_controllers from keystone.common import controller from keystone.common import dependency @dependency.requires('assignment_api', 'catalog_api', 'endpoint_filter_api') class EndpointFilterV3Controller(controller.V3Controller): @controller.protected() def add_endpoint_to_project(self, context, project_id, endpoint_id): """Establishes an association between an endpoint and a project.""" # NOTE(gyee): we just need to make sure endpoint and project exist # first. We don't really care whether if project is disabled. # The relationship can still be established even with a disabled # project as there are no security implications. self.catalog_api.get_endpoint(endpoint_id) self.assignment_api.get_project(project_id) # NOTE(gyee): we may need to cleanup any existing project-endpoint # associations here if either project or endpoint is not found. self.endpoint_filter_api.add_endpoint_to_project(endpoint_id, project_id) @controller.protected() def check_endpoint_in_project(self, context, project_id, endpoint_id): """Verifies endpoint is currently associated with given project.""" self.catalog_api.get_endpoint(endpoint_id) self.assignment_api.get_project(project_id) # TODO(gyee): we may need to cleanup any existing project-endpoint # associations here if either project or endpoint is not found. self.endpoint_filter_api.check_endpoint_in_project(endpoint_id, project_id) @controller.protected() def list_endpoints_for_project(self, context, project_id): """Lists all endpoints currently associated with a given project.""" self.assignment_api.get_project(project_id) refs = self.endpoint_filter_api.list_endpoints_for_project(project_id) endpoints = [self.catalog_api.get_endpoint( ref.endpoint_id) for ref in refs] return catalog_controllers.EndpointV3.wrap_collection(context, endpoints) @controller.protected() def remove_endpoint_from_project(self, context, project_id, endpoint_id): """Remove the endpoint from the association with given project.""" self.endpoint_filter_api.remove_endpoint_from_project(endpoint_id, project_id) @controller.protected() def list_projects_for_endpoint(self, context, endpoint_id): """Return a list of projects associated with the endpoint.""" self.catalog_api.get_endpoint(endpoint_id) refs = self.endpoint_filter_api.list_projects_for_endpoint(endpoint_id) projects = [self.assignment_api.get_project( ref.project_id) for ref in refs] return assignment.controllers.ProjectV3.wrap_collection(context, projects) keystone-2014.1/keystone/contrib/endpoint_filter/core.py0000664000175400017540000001010612323716267024577 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import abc import six from keystone.common import dependency from keystone.common import extension from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) extension_data = { 'name': 'OpenStack Keystone Endpoint Filter API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-EP-FILTER/v1.0', 'alias': 'OS-EP-FILTER', 'updated': '2013-07-23T12:00:0-00:00', 'description': 'OpenStack Keystone Endpoint Filter API.', 'links': [ { 'rel': 'describedby', # TODO(ayoung): needs a description 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api/blob/master' '/openstack-identity-api/v3/src/markdown/' 'identity-api-v3-os-ep-filter-ext.md', } ]} extension.register_admin_extension(extension_data['alias'], extension_data) @dependency.provider('endpoint_filter_api') class Manager(manager.Manager): """Default pivot point for the Endpoint Filter backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): super(Manager, self).__init__(CONF.endpoint_filter.driver) @six.add_metaclass(abc.ABCMeta) class Driver(object): """Interface description for an Endpoint Filter driver.""" @abc.abstractmethod def add_endpoint_to_project(self, endpoint_id, project_id): """Creates an endpoint to project association. :param endpoint_id: identity of endpoint to associate :type endpoint_id: string :param project_id: identity of the project to be associated with :type project_id: string :raises: keystone.exception.Conflict, :returns: None. """ raise exception.NotImplemented() @abc.abstractmethod def remove_endpoint_from_project(self, endpoint_id, project_id): """Removes an endpoint to project association. :param endpoint_id: identity of endpoint to remove :type endpoint_id: string :param project_id: identity of the project associated with :type project_id: string :raises: exception.NotFound :returns: None. """ raise exception.NotImplemented() @abc.abstractmethod def check_endpoint_in_project(self, endpoint_id, project_id): """Checks if an endpoint is associated with a project. :param endpoint_id: identity of endpoint to check :type endpoint_id: string :param project_id: identity of the project associated with :type project_id: string :raises: exception.NotFound :returns: None. """ raise exception.NotImplemented() @abc.abstractmethod def list_endpoints_for_project(self, project_id): """List all endpoints associated with a project. :param project_id: identity of the project to check :type project_id: string :returns: a list of identity endpoint ids or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def list_projects_for_endpoint(self, endpoint_id): """List all projects associated with an endpoint. :param endpoint_id: identity of endpoint to check :type endpoint_id: string :returns: a list of projects or an empty list. """ raise exception.NotImplemented() keystone-2014.1/keystone/contrib/endpoint_filter/routers.py0000664000175400017540000000424712323716267025363 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import wsgi from keystone.contrib.endpoint_filter import controllers class EndpointFilterExtension(wsgi.ExtensionRouter): PATH_PREFIX = '/OS-EP-FILTER' PATH_PROJECT_ENDPOINT = '/projects/{project_id}/endpoints/{endpoint_id}' def add_routes(self, mapper): endpoint_filter_controller = controllers.EndpointFilterV3Controller() mapper.connect(self.PATH_PREFIX + '/endpoints/{endpoint_id}/projects', controller=endpoint_filter_controller, action='list_projects_for_endpoint', conditions=dict(method=['GET'])) mapper.connect(self.PATH_PREFIX + self.PATH_PROJECT_ENDPOINT, controller=endpoint_filter_controller, action='add_endpoint_to_project', conditions=dict(method=['PUT'])) mapper.connect(self.PATH_PREFIX + self.PATH_PROJECT_ENDPOINT, controller=endpoint_filter_controller, action='check_endpoint_in_project', conditions=dict(method=['HEAD'])) mapper.connect(self.PATH_PREFIX + '/projects/{project_id}/endpoints', controller=endpoint_filter_controller, action='list_endpoints_for_project', conditions=dict(method=['GET'])) mapper.connect(self.PATH_PREFIX + self.PATH_PROJECT_ENDPOINT, controller=endpoint_filter_controller, action='remove_endpoint_from_project', conditions=dict(method=['DELETE'])) keystone-2014.1/keystone/contrib/endpoint_filter/backends/0000775000175400017540000000000012323716511025041 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/backends/sql.py0000664000175400017540000000663012323716272026223 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.contrib import endpoint_filter from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.gettextutils import _ class ProjectEndpoint(sql.ModelBase, sql.DictBase): """project-endpoint relationship table.""" __tablename__ = 'project_endpoint' attributes = ['endpoint_id', 'project_id'] endpoint_id = sql.Column(sql.String(64), primary_key=True, nullable=False) project_id = sql.Column(sql.String(64), primary_key=True, nullable=False) class EndpointFilter(object): # Internal interface to manage the database def db_sync(self, version=None): abs_path = migration_helpers.find_migrate_repo(endpoint_filter) migration.db_sync(sql.get_engine(), abs_path, version=version) @sql.handle_conflicts(conflict_type='project_endpoint') def add_endpoint_to_project(self, endpoint_id, project_id): session = sql.get_session() with session.begin(): endpoint_filter_ref = ProjectEndpoint(endpoint_id=endpoint_id, project_id=project_id) session.add(endpoint_filter_ref) def _get_project_endpoint_ref(self, session, endpoint_id, project_id): endpoint_filter_ref = session.query(ProjectEndpoint).get( (endpoint_id, project_id)) if endpoint_filter_ref is None: msg = _('Endpoint %(endpoint_id)s not found in project ' '%(project_id)s') % {'endpoint_id': endpoint_id, 'project_id': project_id} raise exception.NotFound(msg) return endpoint_filter_ref def check_endpoint_in_project(self, endpoint_id, project_id): session = sql.get_session() self._get_project_endpoint_ref(session, endpoint_id, project_id) def remove_endpoint_from_project(self, endpoint_id, project_id): session = sql.get_session() endpoint_filter_ref = self._get_project_endpoint_ref( session, endpoint_id, project_id) with session.begin(): session.delete(endpoint_filter_ref) def list_endpoints_for_project(self, project_id): session = sql.get_session() query = session.query(ProjectEndpoint) query = query.filter_by(project_id=project_id) endpoint_filter_refs = query.all() return endpoint_filter_refs def list_projects_for_endpoint(self, endpoint_id): session = sql.get_session() query = session.query(ProjectEndpoint) query = query.filter_by(endpoint_id=endpoint_id) endpoint_filter_refs = query.all() return endpoint_filter_refs keystone-2014.1/keystone/contrib/endpoint_filter/backends/catalog_sql.py0000664000175400017540000000554712323716267027727 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import six from keystone.catalog.backends import sql from keystone.catalog import core as catalog_core from keystone.common import dependency from keystone import config from keystone import exception CONF = config.CONF @dependency.requires('endpoint_filter_api') class EndpointFilterCatalog(sql.Catalog): def get_v3_catalog(self, user_id, project_id, metadata=None): d = dict(six.iteritems(CONF)) d.update({'tenant_id': project_id, 'user_id': user_id}) services = {} refs = self.endpoint_filter_api.list_endpoints_for_project(project_id) if (not refs and CONF.endpoint_filter.return_all_endpoints_if_no_filter): return super(EndpointFilterCatalog, self).get_v3_catalog( user_id, project_id, metadata=metadata) for entry in refs: try: endpoint = self.get_endpoint(entry.endpoint_id) if not endpoint['enabled']: # Skip disabled endpoints. continue service_id = endpoint['service_id'] services.setdefault( service_id, self.get_service(service_id)) service = services[service_id] del endpoint['service_id'] del endpoint['enabled'] del endpoint['legacy_endpoint_id'] endpoint['url'] = catalog_core.format_url( endpoint['url'], d) # populate filtered endpoints if 'endpoints' in services[service_id]: service['endpoints'].append(endpoint) else: service['endpoints'] = [endpoint] except exception.EndpointNotFound: # remove bad reference from association self.endpoint_filter_api.remove_endpoint_from_project( entry.endpoint_id, project_id) # format catalog catalog = [] for service_id, service in six.iteritems(services): formatted_service = {} formatted_service['id'] = service['id'] formatted_service['type'] = service['type'] formatted_service['endpoints'] = service['endpoints'] catalog.append(formatted_service) return catalog keystone-2014.1/keystone/contrib/endpoint_filter/backends/__init__.py0000664000175400017540000000000012323716267027150 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/0000775000175400017540000000000012323716511025744 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/versions/0000775000175400017540000000000012323716511027614 5ustar jenkinsjenkins00000000000000././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_table.pykeystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_ta0000664000175400017540000000273112323716267035311 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine endpoint_filtering_table = sql.Table( 'project_endpoint', meta, sql.Column( 'endpoint_id', sql.String(64), primary_key=True, nullable=False), sql.Column( 'project_id', sql.String(64), primary_key=True, nullable=False)) endpoint_filtering_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine # Operations to reverse the above upgrade go here. for table_name in ['project_endpoint']: table = sql.Table(table_name, meta, autoload=True) table.drop() keystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/versions/__init__.py0000664000175400017540000000000012323716267031723 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/migrate.cfg0000664000175400017540000000232312323716267030065 0ustar jenkinsjenkins00000000000000[db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. repository_id=endpoint_filter # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. # If this is changed once a database is under version control, you'll need to # change the table name in each database too. version_table=migrate_version # When committing a change script, Migrate will attempt to generate the # sql for all supported databases; normally, if one of them fails - probably # because you don't have that database installed - it is ignored and the # commit continues, perhaps ending successfully. # Databases in this list MUST compile successfully during a commit, or the # entire commit will fail. List the databases your application will actually # be using to ensure your updates to that database work properly. # This must be a list; example: ['postgres','sqlite'] required_dbs=[] # When creating new change scripts, Migrate will stamp the new script with # a version number. By default this is latest_version + 1. You can set this # to 'true' to tell Migrate to use the UTC timestamp instead. use_timestamp_numbering=False keystone-2014.1/keystone/contrib/endpoint_filter/migrate_repo/__init__.py0000664000175400017540000000000012323716267030053 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/endpoint_filter/__init__.py0000664000175400017540000000121612323716272025404 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2013 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. from keystone.contrib.endpoint_filter.core import * keystone-2014.1/keystone/contrib/example/0000775000175400017540000000000012323716511021535 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/example/configuration.rst0000664000175400017540000000210112323716267025140 0ustar jenkinsjenkins00000000000000.. Copyright 2013 OpenStack, Foundation All Rights Reserved. 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. ================= Extension Example ================= Please describe here in details how to enable your extension: 1. Add the required fields and values in the ``[example]`` section in ``keystone.conf``. 2. Optional: add the required ``filter`` to the ``pipeline`` in ``keystone-paste.ini`` 3. Optional: create the extension tables if using the provided sql backend. Example:: ./bin/keystone-manage db_sync --extension examplekeystone-2014.1/keystone/contrib/example/controllers.py0000664000175400017540000000162612323716267024472 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import controller from keystone.common import dependency @dependency.requires('example_api') class ExampleV3Controller(controller.V3Controller): @controller.protected() def example_get(self, context): """Description of the controller logic.""" self.example_api.do_something(context) keystone-2014.1/keystone/contrib/example/core.py0000664000175400017540000000660712323716267023060 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import dependency from keystone.common import manager from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) @dependency.provider('example_api') class ExampleManager(manager.Manager): """Example Manager. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ def __init__(self): # The following is an example of event callbacks. In this setup, # ExampleManager's data model is depended on project's data model. # It must create additional aggregates when a new project is created, # and it must cleanup data related to the project whenever a project # has been deleted. # # In this example, the project_deleted_callback will be invoked # whenever a project has been deleted. Similarly, the # project_created_callback will be invoked whenever a new project is # created. # This information is used when the @dependency.provider decorator acts # on the class. self.event_callbacks = { 'deleted': { 'project': [ self.project_deleted_callback]}, 'created': { 'project': [ self.project_created_callback]}} super(ExampleManager, self).__init__( 'keystone.contrib.example.core.ExampleDriver') def project_deleted_callback(self, service, resource_type, operation, payload): # The code below is merely an example. msg = _('Received the following notification: service %(service)s, ' 'resource_type: %(resource_type)s, operation %(operation)s ' 'payload %(payload)s') LOG.info(msg, {'service': service, 'resource_type': resource_type, 'operation': operation, 'payload': payload}) def project_created_callback(self, service, resource_type, operation, payload): # The code below is merely an example. msg = _('Received the following notification: service %(service)s, ' 'resource_type: %(resource_type)s, operation %(operation)s ' 'payload %(payload)s') LOG.info(msg, {'service': service, 'resource_type': resource_type, 'operation': operation, 'payload': payload}) class ExampleDriver(object): """Interface description for Example driver.""" def do_something(self, data): """Do something :param data: example data :type data: string :raises: keystone.exception, :returns: None. """ raise exception.NotImplemented() keystone-2014.1/keystone/contrib/example/routers.py0000664000175400017540000000203612323716267023623 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import wsgi from keystone.contrib.example import controllers class ExampleRouter(wsgi.ExtensionRouter): PATH_PREFIX = '/OS-EXAMPLE' def add_routes(self, mapper): example_controller = controllers.ExampleV3Controller() mapper.connect(self.PATH_PREFIX + '/example', controller=example_controller, action='do_something', conditions=dict(method=['GET'])) keystone-2014.1/keystone/contrib/example/migrate_repo/0000775000175400017540000000000012323716511024212 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/example/migrate_repo/versions/0000775000175400017540000000000012323716511026062 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/example/migrate_repo/versions/001_example_table.py0000664000175400017540000000255012323716267031630 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine # catalog service_table = sql.Table( 'example', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('type', sql.String(255)), sql.Column('extra', sql.Text())) service_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): # Operations to reverse the above upgrade go here. meta = sql.MetaData() meta.bind = migrate_engine tables = ['example'] for t in tables: table = sql.Table(t, meta, autoload=True) table.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/contrib/example/migrate_repo/versions/__init__.py0000664000175400017540000000000012323716267030171 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/example/migrate_repo/migrate.cfg0000664000175400017540000000231312323716267026332 0ustar jenkinsjenkins00000000000000[db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. repository_id=example # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. # If this is changed once a database is under version control, you'll need to # change the table name in each database too. version_table=migrate_version # When committing a change script, Migrate will attempt to generate the # sql for all supported databases; normally, if one of them fails - probably # because you don't have that database installed - it is ignored and the # commit continues, perhaps ending successfully. # Databases in this list MUST compile successfully during a commit, or the # entire commit will fail. List the databases your application will actually # be using to ensure your updates to that database work properly. # This must be a list; example: ['postgres','sqlite'] required_dbs=[] # When creating new change scripts, Migrate will stamp the new script with # a version number. By default this is latest_version + 1. You can set this # to 'true' to tell Migrate to use the UTC timestamp instead. use_timestamp_numbering=False keystone-2014.1/keystone/contrib/example/migrate_repo/__init__.py0000664000175400017540000000000012323716267026321 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/example/__init__.py0000664000175400017540000000000012323716267023644 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/ec2/0000775000175400017540000000000012323716511020553 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/ec2/controllers.py0000664000175400017540000004052412323716267023510 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Main entry point into the EC2 Credentials service. This service allows the creation of access/secret credentials used for the ec2 interop layer of OpenStack. A user can create as many access/secret pairs, each of which map to a specific project. This is required because OpenStack supports a user belonging to multiple projects, whereas the signatures created on ec2-style requests don't allow specification of which project the user wishes to act upon. To complete the cycle, we provide a method that OpenStack services can use to validate a signature and get a corresponding OpenStack token. This token allows method calls to other services within the context the access/secret was created. As an example, Nova requests Keystone to validate the signature of a request, receives a token, and then makes a request to Glance to list images needed to perform the requested task. """ import abc import uuid import six from keystoneclient.contrib.ec2 import utils as ec2_utils from keystone.common import controller from keystone.common import dependency from keystone.common import utils from keystone.common import wsgi from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils from keystone import token @dependency.requires('assignment_api', 'catalog_api', 'credential_api', 'identity_api', 'token_api') @six.add_metaclass(abc.ABCMeta) class Ec2ControllerCommon(object): def check_signature(self, creds_ref, credentials): signer = ec2_utils.Ec2Signer(creds_ref['secret']) signature = signer.generate(credentials) if utils.auth_str_equal(credentials['signature'], signature): return # NOTE(vish): Some libraries don't use the port when signing # requests, so try again without port. elif ':' in credentials['signature']: hostname, _port = credentials['host'].split(':') credentials['host'] = hostname signature = signer.generate(credentials) if not utils.auth_str_equal(credentials.signature, signature): raise exception.Unauthorized(message='Invalid EC2 signature.') else: raise exception.Unauthorized(message='EC2 signature not supplied.') @abc.abstractmethod def authenticate(self, context, credentials=None, ec2Credentials=None): """Validate a signed EC2 request and provide a token. Other services (such as Nova) use this **admin** call to determine if a request they signed received is from a valid user. If it is a valid signature, an OpenStack token that maps to the user/tenant is returned to the caller, along with all the other details returned from a normal token validation call. The returned token is useful for making calls to other OpenStack services within the context of the request. :param context: standard context :param credentials: dict of ec2 signature :param ec2Credentials: DEPRECATED dict of ec2 signature :returns: token: OpenStack token equivalent to access key along with the corresponding service catalog and roles """ raise exception.NotImplemented() def _authenticate(self, credentials=None, ec2credentials=None): """Common code shared between the V2 and V3 authenticate methods. :returns: user_ref, tenant_ref, metadata_ref, roles_ref, catalog_ref """ # FIXME(ja): validate that a service token was used! # NOTE(termie): backwards compat hack if not credentials and ec2credentials: credentials = ec2credentials if 'access' not in credentials: raise exception.Unauthorized(message='EC2 signature not supplied.') creds_ref = self._get_credentials(credentials['access']) self.check_signature(creds_ref, credentials) # TODO(termie): don't create new tokens every time # TODO(termie): this is copied from TokenController.authenticate tenant_ref = self.assignment_api.get_project(creds_ref['tenant_id']) user_ref = self.identity_api.get_user(creds_ref['user_id']) metadata_ref = {} metadata_ref['roles'] = ( self.assignment_api.get_roles_for_user_and_project( user_ref['id'], tenant_ref['id'])) trust_id = creds_ref.get('trust_id') if trust_id: metadata_ref['trust_id'] = trust_id metadata_ref['trustee_user_id'] = user_ref['id'] # Validate that the auth info is valid and nothing is disabled token.validate_auth_info(self, user_ref, tenant_ref) roles = metadata_ref.get('roles', []) if not roles: raise exception.Unauthorized(message='User not valid for tenant.') roles_ref = [self.assignment_api.get_role(role_id) for role_id in roles] catalog_ref = self.catalog_api.get_catalog( user_ref['id'], tenant_ref['id'], metadata_ref) return user_ref, tenant_ref, metadata_ref, roles_ref, catalog_ref def create_credential(self, context, user_id, tenant_id): """Create a secret/access pair for use with ec2 style auth. Generates a new set of credentials that map the user/tenant pair. :param context: standard context :param user_id: id of user :param tenant_id: id of tenant :returns: credential: dict of ec2 credential """ self.identity_api.get_user(user_id) self.assignment_api.get_project(tenant_id) trust_id = self._get_trust_id_for_request(context) blob = {'access': uuid.uuid4().hex, 'secret': uuid.uuid4().hex, 'trust_id': trust_id} credential_id = utils.hash_access_key(blob['access']) cred_ref = {'user_id': user_id, 'project_id': tenant_id, 'blob': jsonutils.dumps(blob), 'id': credential_id, 'type': 'ec2'} self.credential_api.create_credential(credential_id, cred_ref) return {'credential': self._convert_v3_to_ec2_credential(cred_ref)} def get_credentials(self, user_id): """List all credentials for a user. :param user_id: id of user :returns: credentials: list of ec2 credential dicts """ self.identity_api.get_user(user_id) credential_refs = self.credential_api.list_credentials( user_id=user_id) return {'credentials': [self._convert_v3_to_ec2_credential(credential) for credential in credential_refs]} def get_credential(self, user_id, credential_id): """Retrieve a user's access/secret pair by the access key. Grab the full access/secret pair for a given access key. :param user_id: id of user :param credential_id: access key for credentials :returns: credential: dict of ec2 credential """ self.identity_api.get_user(user_id) return {'credential': self._get_credentials(credential_id)} def delete_credential(self, user_id, credential_id): """Delete a user's access/secret pair. Used to revoke a user's access/secret pair :param user_id: id of user :param credential_id: access key for credentials :returns: bool: success """ self.identity_api.get_user(user_id) self._get_credentials(credential_id) ec2_credential_id = utils.hash_access_key(credential_id) return self.credential_api.delete_credential(ec2_credential_id) @staticmethod def _convert_v3_to_ec2_credential(credential): # Prior to bug #1259584 fix, blob was stored unserialized # but it should be stored as a json string for compatibility # with the v3 credentials API. Fall back to the old behavior # for backwards compatibility with existing DB contents try: blob = jsonutils.loads(credential['blob']) except TypeError: blob = credential['blob'] return {'user_id': credential.get('user_id'), 'tenant_id': credential.get('project_id'), 'access': blob.get('access'), 'secret': blob.get('secret'), 'trust_id': blob.get('trust_id')} def _get_credentials(self, credential_id): """Return credentials from an ID. :param credential_id: id of credential :raises exception.Unauthorized: when credential id is invalid :returns: credential: dict of ec2 credential. """ ec2_credential_id = utils.hash_access_key(credential_id) creds = self.credential_api.get_credential(ec2_credential_id) if not creds: raise exception.Unauthorized(message='EC2 access key not found.') return self._convert_v3_to_ec2_credential(creds) @dependency.requires('policy_api', 'token_provider_api') class Ec2Controller(Ec2ControllerCommon, controller.V2Controller): @controller.v2_deprecated def authenticate(self, context, credentials=None, ec2Credentials=None): (user_ref, tenant_ref, metadata_ref, roles_ref, catalog_ref) = self._authenticate(credentials=credentials, ec2credentials=ec2Credentials) # NOTE(morganfainberg): Make sure the data is in correct form since it # might be consumed external to Keystone and this is a v2.0 controller. # The token provider does not explicitly care about user_ref version # in this case, but the data is stored in the token itself and should # match the version user_ref = self.v3_to_v2_user(user_ref) auth_token_data = dict(user=user_ref, tenant=tenant_ref, metadata=metadata_ref, id='placeholder') (token_id, token_data) = self.token_provider_api.issue_v2_token( auth_token_data, roles_ref, catalog_ref) return token_data @controller.v2_deprecated def get_credential(self, context, user_id, credential_id): if not self._is_admin(context): self._assert_identity(context, user_id) return super(Ec2Controller, self).get_credential(user_id, credential_id) @controller.v2_deprecated def get_credentials(self, context, user_id): if not self._is_admin(context): self._assert_identity(context, user_id) return super(Ec2Controller, self).get_credentials(user_id) @controller.v2_deprecated def create_credential(self, context, user_id, tenant_id): if not self._is_admin(context): self._assert_identity(context, user_id) return super(Ec2Controller, self).create_credential(context, user_id, tenant_id) @controller.v2_deprecated def delete_credential(self, context, user_id, credential_id): if not self._is_admin(context): self._assert_identity(context, user_id) self._assert_owner(user_id, credential_id) return super(Ec2Controller, self).delete_credential(user_id, credential_id) def _assert_identity(self, context, user_id): """Check that the provided token belongs to the user. :param context: standard context :param user_id: id of user :raises exception.Forbidden: when token is invalid """ try: token_ref = self.token_api.get_token(context['token_id']) except exception.TokenNotFound as e: raise exception.Unauthorized(e) if token_ref['user'].get('id') != user_id: raise exception.Forbidden(_('Token belongs to another user')) def _is_admin(self, context): """Wrap admin assertion error return statement. :param context: standard context :returns: bool: success """ try: # NOTE(morganfainberg): policy_api is required for assert_admin # to properly perform policy enforcement. self.assert_admin(context) return True except exception.Forbidden: return False def _assert_owner(self, user_id, credential_id): """Ensure the provided user owns the credential. :param user_id: expected credential owner :param credential_id: id of credential object :raises exception.Forbidden: on failure """ ec2_credential_id = utils.hash_access_key(credential_id) cred_ref = self.credential_api.get_credential(ec2_credential_id) if user_id != cred_ref['user_id']: raise exception.Forbidden(_('Credential belongs to another user')) @dependency.requires('policy_api', 'token_provider_api') class Ec2ControllerV3(Ec2ControllerCommon, controller.V3Controller): member_name = 'project' def __init__(self): super(Ec2ControllerV3, self).__init__() self.get_member_from_driver = self.credential_api.get_credential def _check_credential_owner_and_user_id_match(self, context, prep_info, user_id, credential_id): # NOTE(morganfainberg): this method needs to capture the arguments of # the method that is decorated with @controller.protected() (with # exception of the first argument ('context') since the protected # method passes in *args, **kwargs. In this case, it is easier to see # the expected input if the argspec is `user_id` and `credential_id` # explicitly (matching the :class:`.ec2_delete_credential()` method # below). ref = {} credential_id = utils.hash_access_key(credential_id) ref['credential'] = self.credential_api.get_credential(credential_id) # NOTE(morganfainberg): policy_api is required for this # check_protection to properly be able to perform policy enforcement. self.check_protection(context, prep_info, ref) def authenticate(self, context, credentials=None, ec2Credentials=None): (user_ref, project_ref, metadata_ref, roles_ref, catalog_ref) = self._authenticate(credentials=credentials, ec2credentials=ec2Credentials) method_names = ['ec2credential'] token_id, token_data = self.token_provider_api.issue_v3_token( user_ref['id'], method_names, project_id=project_ref['id'], metadata_ref=metadata_ref) return render_token_data_response(token_id, token_data) @controller.protected() def ec2_get_credential(self, context, user_id, credential_id): return super(Ec2ControllerV3, self).get_credential(user_id, credential_id) @controller.protected() def ec2_list_credentials(self, context, user_id): return super(Ec2ControllerV3, self).get_credentials(user_id) @controller.protected() def ec2_create_credential(self, context, user_id, tenant_id): return super(Ec2ControllerV3, self).create_credential(context, user_id, tenant_id) @controller.protected(callback=_check_credential_owner_and_user_id_match) def ec2_delete_credential(self, context, user_id, credential_id): return super(Ec2ControllerV3, self).delete_credential(user_id, credential_id) def render_token_data_response(token_id, token_data): """Render token data HTTP response. Stash token ID into the X-Subject-Token header. """ headers = [('X-Subject-Token', token_id)] return wsgi.render_response(body=token_data, status=(200, 'OK'), headers=headers) keystone-2014.1/keystone/contrib/ec2/core.py0000664000175400017540000000244712323716267022074 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import extension from keystone import config CONF = config.CONF EXTENSION_DATA = { 'name': 'OpenStack EC2 API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-EC2/v1.0', 'alias': 'OS-EC2', 'updated': '2013-07-07T12:00:0-00:00', 'description': 'OpenStack EC2 Credentials backend.', 'links': [ { 'rel': 'describedby', # TODO(ayoung): needs a description 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) keystone-2014.1/keystone/contrib/ec2/routers.py0000664000175400017540000000571012323716267022643 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import wsgi from keystone.contrib.ec2 import controllers class Ec2Extension(wsgi.ExtensionRouter): def add_routes(self, mapper): ec2_controller = controllers.Ec2Controller() # validation mapper.connect( '/ec2tokens', controller=ec2_controller, action='authenticate', conditions=dict(method=['POST'])) # crud mapper.connect( '/users/{user_id}/credentials/OS-EC2', controller=ec2_controller, action='create_credential', conditions=dict(method=['POST'])) mapper.connect( '/users/{user_id}/credentials/OS-EC2', controller=ec2_controller, action='get_credentials', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/credentials/OS-EC2/{credential_id}', controller=ec2_controller, action='get_credential', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/credentials/OS-EC2/{credential_id}', controller=ec2_controller, action='delete_credential', conditions=dict(method=['DELETE'])) class Ec2ExtensionV3(wsgi.ExtensionRouter): def add_routes(self, mapper): ec2_controller = controllers.Ec2ControllerV3() # validation mapper.connect( '/ec2tokens', controller=ec2_controller, action='authenticate', conditions=dict(method=['POST'])) # crud mapper.connect( '/users/{user_id}/credentials/OS-EC2', controller=ec2_controller, action='ec2_create_credential', conditions=dict(method=['POST'])) mapper.connect( '/users/{user_id}/credentials/OS-EC2', controller=ec2_controller, action='ec2_list_credentials', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/credentials/OS-EC2/{credential_id}', controller=ec2_controller, action='ec2_get_credential', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/credentials/OS-EC2/{credential_id}', controller=ec2_controller, action='ec2_delete_credential', conditions=dict(method=['DELETE'])) keystone-2014.1/keystone/contrib/ec2/__init__.py0000664000175400017540000000143512323716272022673 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.contrib.ec2 import controllers from keystone.contrib.ec2.core import * from keystone.contrib.ec2.routers import Ec2Extension from keystone.contrib.ec2.routers import Ec2ExtensionV3 keystone-2014.1/keystone/contrib/simple_cert/0000775000175400017540000000000012323716511022410 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/simple_cert/controllers.py0000664000175400017540000000330712323716267025343 0ustar jenkinsjenkins00000000000000# 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 oslo.config import cfg import webob from keystone.common import controller from keystone.common import dependency from keystone import exception from keystone.token.providers import pki CONF = cfg.CONF @dependency.requires('token_provider_api') class SimpleCert(controller.V3Controller): def _get_certificate(self, name): # If we aren't using the PKI Provider then we should return a 403 if not isinstance(self.token_provider_api.driver, pki.Provider): raise exception.PKITokenExpected() try: with open(name, 'r') as f: body = f.read() except IOError: raise exception.CertificateFilesUnavailable() # NOTE(jamielennox): We construct the webob Response ourselves here so # that we don't pass through the JSON encoding process. headers = [('Content-Type', 'application/x-pem-file')] return webob.Response(body=body, headerlist=headers, status="200 OK") def get_ca_certificate(self, context): return self._get_certificate(CONF.signing.ca_certs) def list_certificates(self, context): return self._get_certificate(CONF.signing.certfile) keystone-2014.1/keystone/contrib/simple_cert/core.py0000664000175400017540000000246212323716267023726 0ustar jenkinsjenkins00000000000000# 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 keystone.common import extension EXTENSION_DATA = { 'name': 'OpenStack Simple Certificate API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-SIMPLE-CERT/v1.0', 'alias': 'OS-SIMPLE-CERT', 'updated': '2014-01-20T12:00:0-00:00', 'description': 'OpenStack simple certificate retrieval extension', 'links': [ { 'rel': 'describedby', # TODO(dolph): link needs to be revised after # bug 928059 merges 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) keystone-2014.1/keystone/contrib/simple_cert/routers.py0000664000175400017540000000227012323716267024476 0ustar jenkinsjenkins00000000000000# 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 keystone.common import wsgi from keystone.contrib.simple_cert import controllers class SimpleCertExtension(wsgi.ExtensionRouter): PREFIX = 'OS-SIMPLE-CERT' def add_routes(self, mapper): controller = controllers.SimpleCert() mapper.connect('/%s/ca' % self.PREFIX, controller=controller, action='get_ca_certificate', conditions=dict(method=['GET'])) mapper.connect('/%s/certificates' % self.PREFIX, controller=controller, action='list_certificates', conditions=dict(method=['GET'])) keystone-2014.1/keystone/contrib/simple_cert/__init__.py0000664000175400017540000000124712323716272024531 0ustar jenkinsjenkins00000000000000# 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 keystone.contrib.simple_cert.core import * # flake8: noqa from keystone.contrib.simple_cert.routers import SimpleCertExtension keystone-2014.1/keystone/contrib/oauth1/0000775000175400017540000000000012323716511021303 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/controllers.py0000664000175400017540000003505012323716267024236 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Extensions supporting OAuth1.""" from keystone.common import controller from keystone.common import dependency from keystone.common import wsgi from keystone import config from keystone.contrib.oauth1 import core as oauth1 from keystone.contrib.oauth1 import validator from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils from keystone.openstack.common import timeutils CONF = config.CONF @dependency.requires('oauth_api', 'token_api') class ConsumerCrudV3(controller.V3Controller): collection_name = 'consumers' member_name = 'consumer' @classmethod def base_url(cls, context, path=None): """Construct a path and pass it to V3Controller.base_url method.""" # NOTE(stevemar): Overriding path to /OS-OAUTH1/consumers so that # V3Controller.base_url handles setting the self link correctly. path = '/OS-OAUTH1/' + cls.collection_name return controller.V3Controller.base_url(context, path=path) @controller.protected() def create_consumer(self, context, consumer): ref = self._assign_unique_id(self._normalize_dict(consumer)) consumer_ref = self.oauth_api.create_consumer(ref) return ConsumerCrudV3.wrap_member(context, consumer_ref) @controller.protected() def update_consumer(self, context, consumer_id, consumer): self._require_matching_id(consumer_id, consumer) ref = self._normalize_dict(consumer) self._validate_consumer_ref(ref) ref = self.oauth_api.update_consumer(consumer_id, ref) return ConsumerCrudV3.wrap_member(context, ref) @controller.protected() def list_consumers(self, context): ref = self.oauth_api.list_consumers() return ConsumerCrudV3.wrap_collection(context, ref) @controller.protected() def get_consumer(self, context, consumer_id): ref = self.oauth_api.get_consumer(consumer_id) return ConsumerCrudV3.wrap_member(context, ref) @controller.protected() def delete_consumer(self, context, consumer_id): user_token_ref = self.token_api.get_token(context['token_id']) user_id = user_token_ref['user'].get('id') self.token_api.delete_tokens(user_id, consumer_id=consumer_id) self.oauth_api.delete_consumer(consumer_id) def _validate_consumer_ref(self, consumer): if 'secret' in consumer: msg = _('Cannot change consumer secret') raise exception.ValidationError(message=msg) @dependency.requires('oauth_api', 'token_api') class AccessTokenCrudV3(controller.V3Controller): collection_name = 'access_tokens' member_name = 'access_token' @controller.protected() def get_access_token(self, context, user_id, access_token_id): access_token = self.oauth_api.get_access_token(access_token_id) if access_token['authorizing_user_id'] != user_id: raise exception.NotFound() access_token = self._format_token_entity(context, access_token) return AccessTokenCrudV3.wrap_member(context, access_token) @controller.protected() def list_access_tokens(self, context, user_id): refs = self.oauth_api.list_access_tokens(user_id) formatted_refs = ([self._format_token_entity(context, x) for x in refs]) return AccessTokenCrudV3.wrap_collection(context, formatted_refs) @controller.protected() def delete_access_token(self, context, user_id, access_token_id): access_token = self.oauth_api.get_access_token(access_token_id) consumer_id = access_token['consumer_id'] self.token_api.delete_tokens(user_id, consumer_id=consumer_id) return self.oauth_api.delete_access_token( user_id, access_token_id) def _format_token_entity(self, context, entity): formatted_entity = entity.copy() access_token_id = formatted_entity['id'] user_id = "" if 'role_ids' in entity: formatted_entity.pop('role_ids') if 'access_secret' in entity: formatted_entity.pop('access_secret') if 'authorizing_user_id' in entity: user_id = formatted_entity['authorizing_user_id'] url = ('/users/%(user_id)s/OS-OAUTH1/access_tokens/%(access_token_id)s' '/roles' % {'user_id': user_id, 'access_token_id': access_token_id}) formatted_entity.setdefault('links', {}) formatted_entity['links']['roles'] = (self.base_url(context, url)) return formatted_entity @dependency.requires('assignment_api', 'oauth_api') class AccessTokenRolesV3(controller.V3Controller): collection_name = 'roles' member_name = 'role' @controller.protected() def list_access_token_roles(self, context, user_id, access_token_id): access_token = self.oauth_api.get_access_token(access_token_id) if access_token['authorizing_user_id'] != user_id: raise exception.NotFound() authed_role_ids = access_token['role_ids'] authed_role_ids = jsonutils.loads(authed_role_ids) refs = ([self._format_role_entity(x) for x in authed_role_ids]) return AccessTokenRolesV3.wrap_collection(context, refs) @controller.protected() def get_access_token_role(self, context, user_id, access_token_id, role_id): access_token = self.oauth_api.get_access_token(access_token_id) if access_token['authorizing_user_id'] != user_id: raise exception.Unauthorized(_('User IDs do not match')) authed_role_ids = access_token['role_ids'] authed_role_ids = jsonutils.loads(authed_role_ids) for authed_role_id in authed_role_ids: if authed_role_id == role_id: role = self._format_role_entity(role_id) return AccessTokenRolesV3.wrap_member(context, role) raise exception.RoleNotFound(_('Could not find role')) def _format_role_entity(self, role_id): role = self.assignment_api.get_role(role_id) formatted_entity = role.copy() if 'description' in role: formatted_entity.pop('description') if 'enabled' in role: formatted_entity.pop('enabled') return formatted_entity @dependency.requires('assignment_api', 'oauth_api', 'token_api') class OAuthControllerV3(controller.V3Controller): collection_name = 'not_used' member_name = 'not_used' def create_request_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') requested_project_id = headers.get('Requested-Project-Id') if not consumer_id: raise exception.ValidationError( attribute='oauth_consumer_key', target='request') if not requested_project_id: raise exception.ValidationError( attribute='requested_project_id', target='request') url = self.base_url(context, context['path']) req_headers = {'Requested-Project-Id': requested_project_id} req_headers.update(headers) request_verifier = oauth1.RequestTokenEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth1.token_generator) h, b, s = request_verifier.create_request_token_response( url, http_method='POST', body=context['query_string'], headers=req_headers) if (not b) or int(s) > 399: msg = _('Invalid signature') raise exception.Unauthorized(message=msg) request_token_duration = CONF.oauth1.request_token_duration token_ref = self.oauth_api.create_request_token(consumer_id, requested_project_id, request_token_duration) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % {'key': token_ref['id'], 'secret': token_ref['request_secret']}) if CONF.oauth1.request_token_duration: expiry_bit = '&oauth_expires_at=%s' % token_ref['expires_at'] result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response def create_access_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') request_token_id = oauth_headers.get('oauth_token') oauth_verifier = oauth_headers.get('oauth_verifier') if not consumer_id: raise exception.ValidationError( attribute='oauth_consumer_key', target='request') if not request_token_id: raise exception.ValidationError( attribute='oauth_token', target='request') if not oauth_verifier: raise exception.ValidationError( attribute='oauth_verifier', target='request') req_token = self.oauth_api.get_request_token( request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) url = self.base_url(context, context['path']) access_verifier = oauth1.AccessTokenEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth1.token_generator) h, b, s = access_verifier.create_access_token_response( url, http_method='POST', body=context['query_string'], headers=headers) params = oauth1.extract_non_oauth_params(b) if len(params) != 0: msg = _('There should not be any non-oauth parameters') raise exception.Unauthorized(message=msg) if req_token['consumer_id'] != consumer_id: msg = _('provided consumer key does not match stored consumer key') raise exception.Unauthorized(message=msg) if req_token['verifier'] != oauth_verifier: msg = _('provided verifier does not match stored verifier') raise exception.Unauthorized(message=msg) if req_token['id'] != request_token_id: msg = _('provided request key does not match stored request key') raise exception.Unauthorized(message=msg) if not req_token.get('authorizing_user_id'): msg = _('Request Token does not have an authorizing user id') raise exception.Unauthorized(message=msg) access_token_duration = CONF.oauth1.access_token_duration token_ref = self.oauth_api.create_access_token(request_token_id, access_token_duration) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % {'key': token_ref['id'], 'secret': token_ref['access_secret']}) if CONF.oauth1.access_token_duration: expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at']) result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response @controller.protected() def authorize_request_token(self, context, request_token_id, roles): """An authenticated user is going to authorize a request token. As a security precaution, the requested roles must match those in the request token. Because this is in a CLI-only world at the moment, there is not another easy way to make sure the user knows which roles are being requested before authorizing. """ req_token = self.oauth_api.get_request_token(request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) # put the roles in a set for easy comparison authed_roles = set() for role in roles: authed_roles.add(role['id']) # verify the authorizing user has the roles user_token = self.token_api.get_token(context['token_id']) user_id = user_token['user'].get('id') project_id = req_token['requested_project_id'] user_roles = self.assignment_api.get_roles_for_user_and_project( user_id, project_id) cred_set = set(user_roles) if not cred_set.issuperset(authed_roles): msg = _('authorizing user does not have role required') raise exception.Unauthorized(message=msg) # create list of just the id's for the backend role_list = list(authed_roles) # verify the user has the project too req_project_id = req_token['requested_project_id'] user_projects = self.assignment_api.list_projects_for_user(user_id) found = False for user_project in user_projects: if user_project['id'] == req_project_id: found = True break if not found: msg = _("User is not a member of the requested project") raise exception.Unauthorized(message=msg) # finally authorize the token authed_token = self.oauth_api.authorize_request_token( request_token_id, user_id, role_list) to_return = {'token': {'oauth_verifier': authed_token['verifier']}} return to_return keystone-2014.1/keystone/contrib/oauth1/validator.py0000664000175400017540000001470612323716272023656 0ustar jenkinsjenkins00000000000000# 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. """oAuthlib request validator.""" import six from keystone.common import dependency from keystone.contrib.oauth1 import core as oauth1 from keystone import exception from keystone.openstack.common import log METHOD_NAME = 'oauth_validator' LOG = log.getLogger(__name__) @dependency.requires('oauth_api') class OAuthValidator(oauth1.RequestValidator): #TODO(mhu) set as option probably ? @property def enforce_ssl(self): return False @property def safe_characters(self): #oauth tokens are generated from a uuid hex value return set("abcdef0123456789") def _check_token(self, token): # generic token verification when they're obtained from a uuid hex return (set(token) <= self.safe_characters and len(token) == 32) def check_client_key(self, client_key): return self._check_token(client_key) def check_request_token(self, request_token): return self._check_token(request_token) def check_access_token(self, access_token): return self._check_token(access_token) def check_nonce(self, nonce): # Assuming length is not a concern return set(nonce) <= self.safe_characters def check_verifier(self, verifier): try: return 1000 <= int(verifier) <= 9999 except ValueError: return False def get_client_secret(self, client_key, request): client = self.oauth_api.get_consumer_with_secret(client_key) return client['secret'] def get_request_token_secret(self, client_key, token, request): token_ref = self.oauth_api.get_request_token(token) return token_ref['request_secret'] def get_access_token_secret(self, client_key, token, request): access_token = self.oauth_api.get_access_token(token) return access_token['access_secret'] def get_default_realms(self, client_key, request): # realms weren't implemented with the previous library return [] def get_realms(self, token, request): return [] def get_redirect_uri(self, token, request): # OOB (out of band) is supposed to be the default value to use return 'oob' def get_rsa_key(self, client_key, request): # HMAC signing is used, so return a dummy value return '' def invalidate_request_token(self, client_key, request_token, request): # this method is invoked when an access token is generated out of a # request token, to make sure that request token cannot be consumed # anymore. This is done in the backend, so we do nothing here. pass def validate_client_key(self, client_key, request): try: return self.oauth_api.get_consumer(client_key) is not None except exception.NotFound: return False def validate_request_token(self, client_key, token, request): try: return self.oauth_api.get_request_token(token) is not None except exception.NotFound: return False def validate_access_token(self, client_key, token, request): try: return self.oauth_api.get_access_token(token) is not None except exception.NotFound: return False def validate_timestamp_and_nonce(self, client_key, timestamp, nonce, request, request_token=None, access_token=None): return True def validate_redirect_uri(self, client_key, redirect_uri, request): # we expect OOB, we don't really care return True def validate_requested_realms(self, client_key, realms, request): # realms are not used return True def validate_realms(self, client_key, token, request, uri=None, realms=None): return True def validate_verifier(self, client_key, token, verifier, request): try: req_token = self.oauth_api.get_request_token(token) return req_token['verifier'] == verifier except exception.NotFound: return False def verify_request_token(self, token, request): # there aren't strong expectations on the request token format return isinstance(token, six.string_types) def verify_realms(self, token, realms, request): return True # The following save_XXX methods are called to create tokens. I chose to # keep the original logic, but the comments below show how that could be # implemented. The real implementation logic is in the backend. def save_access_token(self, token, request): pass # token_duration = CONF.oauth1.request_token_duration # request_token_id = request.client_key # self.oauth_api.create_access_token(request_token_id, # token_duration, # token["oauth_token"], # token["oauth_token_secret"]) def save_request_token(self, token, request): pass # project_id = request.headers.get('Requested-Project-Id') # token_duration = CONF.oauth1.request_token_duration # self.oauth_api.create_request_token(request.client_key, # project_id, # token_duration, # token["oauth_token"], # token["oauth_token_secret"]) def save_verifier(self, token, verifier, request): # keep the old logic for this, as it is done in two steps and requires # information that the request validator has no access to pass keystone-2014.1/keystone/contrib/oauth1/core.py0000664000175400017540000002401712323716267022621 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. """Extensions supporting OAuth1.""" from __future__ import absolute_import import abc import oauthlib.common from oauthlib import oauth1 import six import uuid from keystone.common import dependency from keystone.common import extension from keystone.common import manager from keystone import config from keystone import exception from keystone import notifications RequestValidator = oauth1.RequestValidator Client = oauth1.Client AccessTokenEndpoint = oauth1.AccessTokenEndpoint ResourceEndpoint = oauth1.ResourceEndpoint AuthorizationEndpoint = oauth1.AuthorizationEndpoint SIG_HMAC = oauth1.SIGNATURE_HMAC RequestTokenEndpoint = oauth1.RequestTokenEndpoint oRequest = oauthlib.common.Request class Token(object): def __init__(self, key, secret): self.key = key self.secret = secret self.verifier = None def set_verifier(self, verifier): self.verifier = verifier CONF = config.CONF def token_generator(*args, **kwargs): return uuid.uuid4().hex EXTENSION_DATA = { 'name': 'OpenStack OAUTH1 API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-OAUTH1/v1.0', 'alias': 'OS-OAUTH1', 'updated': '2013-07-07T12:00:0-00:00', 'description': 'OpenStack OAuth 1.0a Delegated Auth Mechanism.', 'links': [ { 'rel': 'describedby', # TODO(dolph): link needs to be revised after # bug 928059 merges 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) def filter_consumer(consumer_ref): """Filter out private items in a consumer dict. 'secret' is never returned. :returns: consumer_ref """ if consumer_ref: consumer_ref = consumer_ref.copy() consumer_ref.pop('secret', None) return consumer_ref def filter_token(access_token_ref): """Filter out private items in an access token dict. 'access_secret' is never returned. :returns: access_token_ref """ if access_token_ref: access_token_ref = access_token_ref.copy() access_token_ref.pop('access_secret', None) return access_token_ref def get_oauth_headers(headers): parameters = {} # The incoming headers variable is your usual heading from context # In an OAuth signed req, where the oauth variables are in the header, # they with the key 'Authorization'. if headers and 'Authorization' in headers: # A typical value for Authorization is seen below # 'OAuth realm="", oauth_body_hash="2jm%3D", oauth_nonce="14475435" # along with other oauth variables, the 'OAuth ' part is trimmed # to split the rest of the headers. auth_header = headers['Authorization'] params = oauth1.rfc5849.utils.parse_authorization_header(auth_header) parameters.update(dict(params)) return parameters def extract_non_oauth_params(query_string): params = oauthlib.common.extract_params(query_string) return dict([(k, v) for k, v in params if not k.startswith('oauth_')]) @dependency.provider('oauth_api') class Manager(manager.Manager): """Default pivot point for the OAuth1 backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ _ACCESS_TOKEN = "OS-OAUTH1:access_token" _REQUEST_TOKEN = "OS-OAUTH1:request_token" _CONSUMER = "OS-OAUTH1:consumer" def __init__(self): super(Manager, self).__init__(CONF.oauth1.driver) @notifications.created(_CONSUMER) def create_consumer(self, consumer_ref): return self.driver.create_consumer(consumer_ref) @notifications.updated(_CONSUMER) def update_consumer(self, consumer_id, consumer_ref): return self.driver.update_consumer(consumer_id, consumer_ref) @notifications.deleted(_CONSUMER) def delete_consumer(self, consumer_id): return self.driver.delete_consumer(consumer_id) @notifications.created(_ACCESS_TOKEN) def create_access_token(self, request_id, access_token_duration): return self.driver.create_access_token(request_id, access_token_duration) @notifications.deleted(_ACCESS_TOKEN, resource_id_arg_index=2) def delete_access_token(self, user_id, access_token_id): return self.driver.delete_access_token(user_id, access_token_id) @notifications.created(_REQUEST_TOKEN, resource_id_arg_index=2) def create_request_token(self, consumer_id, requested_project, request_token_duration): return self.driver.create_request_token( consumer_id, requested_project, request_token_duration) @six.add_metaclass(abc.ABCMeta) class Driver(object): """Interface description for an OAuth1 driver.""" @abc.abstractmethod def create_consumer(self, consumer_ref): """Create consumer. :param consumer_ref: consumer ref with consumer name :type consumer_ref: dict :returns: consumer_ref """ raise exception.NotImplemented() @abc.abstractmethod def update_consumer(self, consumer_id, consumer_ref): """Update consumer. :param consumer_id: id of consumer to update :type consumer_id: string :param consumer_ref: new consumer ref with consumer name :type consumer_ref: dict :returns: consumer_ref """ raise exception.NotImplemented() @abc.abstractmethod def list_consumers(self): """List consumers. :returns: list of consumers """ raise exception.NotImplemented() @abc.abstractmethod def get_consumer(self, consumer_id): """Get consumer, returns the consumer id (key) and description. :param consumer_id: id of consumer to get :type consumer_id: string :returns: consumer_ref """ raise exception.NotImplemented() @abc.abstractmethod def get_consumer_with_secret(self, consumer_id): """Like get_consumer() but returned consumer_ref includes the consumer secret. Secrets should only be shared upon consumer creation; the consumer secret is required to verify incoming OAuth requests. :param consumer_id: id of consumer to get :type consumer_id: string :returns: consumer_ref """ raise exception.NotImplemented() @abc.abstractmethod def delete_consumer(self, consumer_id): """Delete consumer. :param consumer_id: id of consumer to get :type consumer_id: string :returns: None. """ raise exception.NotImplemented() @abc.abstractmethod def list_access_tokens(self, user_id): """List access tokens. :param user_id: search for access tokens authorized by given user id :type user_id: string :returns: list of access tokens the user has authorized """ raise exception.NotImplemented() @abc.abstractmethod def delete_access_token(self, user_id, access_token_id): """Delete access token. :param user_id: authorizing user id :type user_id: string :param access_token_id: access token to delete :type access_token_id: string :returns: None """ raise exception.NotImplemented() @abc.abstractmethod def create_request_token(self, consumer_id, requested_project, request_token_duration): """Create request token. :param consumer_id: the id of the consumer :type consumer_id: string :param requested_project_id: requested project id :type requested_project_id: string :param request_token_duration: duration of request token :type request_token_duration: string :returns: request_token_ref """ raise exception.NotImplemented() @abc.abstractmethod def get_request_token(self, request_token_id): """Get request token. :param request_token_id: the id of the request token :type request_token_id: string :returns: request_token_ref """ raise exception.NotImplemented() @abc.abstractmethod def get_access_token(self, access_token_id): """Get access token. :param access_token_id: the id of the access token :type access_token_id: string :returns: access_token_ref """ raise exception.NotImplemented() @abc.abstractmethod def authorize_request_token(self, request_id, user_id, role_ids): """Authorize request token. :param request_id: the id of the request token, to be authorized :type request_id: string :param user_id: the id of the authorizing user :type user_id: string :param role_ids: list of role ids to authorize :type role_ids: list :returns: verifier """ raise exception.NotImplemented() @abc.abstractmethod def create_access_token(self, request_id, access_token_duration): """Create access token. :param request_id: the id of the request token, to be deleted :type request_id: string :param access_token_duration: duration of an access token :type access_token_duration: string :returns: access_token_ref """ raise exception.NotImplemented() keystone-2014.1/keystone/contrib/oauth1/routers.py0000664000175400017540000001214612323716267023374 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.common import wsgi from keystone.contrib import oauth1 from keystone.contrib.oauth1 import controllers class OAuth1Extension(wsgi.ExtensionRouter): """API Endpoints for the OAuth1 extension. The goal of this extension is to allow third-party service providers to acquire tokens with a limited subset of a user's roles for acting on behalf of that user. This is done using an oauth-similar flow and api. The API looks like:: # Basic admin-only consumer crud POST /OS-OAUTH1/consumers GET /OS-OAUTH1/consumers PATCH /OS-OAUTH1/consumers/$consumer_id GET /OS-OAUTH1/consumers/$consumer_id DELETE /OS-OAUTH1/consumers/$consumer_id # User access token crud GET /users/$user_id/OS-OAUTH1/access_tokens GET /users/$user_id/OS-OAUTH1/access_tokens/$access_token_id GET /users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles GET /users/{user_id}/OS-OAUTH1/access_tokens /{access_token_id}/roles/{role_id} DELETE /users/$user_id/OS-OAUTH1/access_tokens/$access_token_id # OAuth interfaces POST /OS-OAUTH1/request_token # create a request token PUT /OS-OAUTH1/authorize # authorize a request token POST /OS-OAUTH1/access_token # create an access token """ def add_routes(self, mapper): # This is needed for dependency injection, # it loads the OAuth driver which registers it as a dependency. oauth1.Manager() consumer_controller = controllers.ConsumerCrudV3() access_token_controller = controllers.AccessTokenCrudV3() access_token_roles_controller = controllers.AccessTokenRolesV3() oauth_controller = controllers.OAuthControllerV3() # basic admin-only consumer crud mapper.connect( '/OS-OAUTH1/consumers', controller=consumer_controller, action='create_consumer', conditions=dict(method=['POST'])) mapper.connect( '/OS-OAUTH1/consumers/{consumer_id}', controller=consumer_controller, action='get_consumer', conditions=dict(method=['GET'])) mapper.connect( '/OS-OAUTH1/consumers/{consumer_id}', controller=consumer_controller, action='update_consumer', conditions=dict(method=['PATCH'])) mapper.connect( '/OS-OAUTH1/consumers/{consumer_id}', controller=consumer_controller, action='delete_consumer', conditions=dict(method=['DELETE'])) mapper.connect( '/OS-OAUTH1/consumers', controller=consumer_controller, action='list_consumers', conditions=dict(method=['GET'])) # user accesss token crud mapper.connect( '/users/{user_id}/OS-OAUTH1/access_tokens', controller=access_token_controller, action='list_access_tokens', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}', controller=access_token_controller, action='get_access_token', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}', controller=access_token_controller, action='delete_access_token', conditions=dict(method=['DELETE'])) mapper.connect( '/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles', controller=access_token_roles_controller, action='list_access_token_roles', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/OS-OAUTH1/access_tokens/' '{access_token_id}/roles/{role_id}', controller=access_token_roles_controller, action='get_access_token_role', conditions=dict(method=['GET'])) # oauth flow calls mapper.connect( '/OS-OAUTH1/request_token', controller=oauth_controller, action='create_request_token', conditions=dict(method=['POST'])) mapper.connect( '/OS-OAUTH1/access_token', controller=oauth_controller, action='create_access_token', conditions=dict(method=['POST'])) mapper.connect( '/OS-OAUTH1/authorize/{request_token_id}', controller=oauth_controller, action='authorize_request_token', conditions=dict(method=['PUT'])) keystone-2014.1/keystone/contrib/oauth1/backends/0000775000175400017540000000000012323716511023055 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/backends/sql.py0000664000175400017540000002676712323716272024254 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import datetime import random import uuid import six from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.contrib import oauth1 from keystone.contrib.oauth1 import core from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import jsonutils from keystone.openstack.common import timeutils class Consumer(sql.ModelBase, sql.DictBase): __tablename__ = 'consumer' attributes = ['id', 'description', 'secret'] id = sql.Column(sql.String(64), primary_key=True, nullable=False) description = sql.Column(sql.String(64), nullable=True) secret = sql.Column(sql.String(64), nullable=False) extra = sql.Column(sql.JsonBlob(), nullable=False) class RequestToken(sql.ModelBase, sql.DictBase): __tablename__ = 'request_token' attributes = ['id', 'request_secret', 'verifier', 'authorizing_user_id', 'requested_project_id', 'role_ids', 'consumer_id', 'expires_at'] id = sql.Column(sql.String(64), primary_key=True, nullable=False) request_secret = sql.Column(sql.String(64), nullable=False) verifier = sql.Column(sql.String(64), nullable=True) authorizing_user_id = sql.Column(sql.String(64), nullable=True) requested_project_id = sql.Column(sql.String(64), nullable=False) role_ids = sql.Column(sql.Text(), nullable=True) consumer_id = sql.Column(sql.String(64), sql.ForeignKey('consumer.id'), nullable=False, index=True) expires_at = sql.Column(sql.String(64), nullable=True) @classmethod def from_dict(cls, user_dict): return cls(**user_dict) def to_dict(self): return dict(six.iteritems(self)) class AccessToken(sql.ModelBase, sql.DictBase): __tablename__ = 'access_token' attributes = ['id', 'access_secret', 'authorizing_user_id', 'project_id', 'role_ids', 'consumer_id', 'expires_at'] id = sql.Column(sql.String(64), primary_key=True, nullable=False) access_secret = sql.Column(sql.String(64), nullable=False) authorizing_user_id = sql.Column(sql.String(64), nullable=False, index=True) project_id = sql.Column(sql.String(64), nullable=False) role_ids = sql.Column(sql.Text(), nullable=False) consumer_id = sql.Column(sql.String(64), sql.ForeignKey('consumer.id'), nullable=False) expires_at = sql.Column(sql.String(64), nullable=True) @classmethod def from_dict(cls, user_dict): return cls(**user_dict) def to_dict(self): return dict(six.iteritems(self)) class OAuth1(object): def db_sync(self): migration.db_sync(sql.get_engine(), migration_helpers.find_migrate_repo(oauth1)) def _get_consumer(self, session, consumer_id): consumer_ref = session.query(Consumer).get(consumer_id) if consumer_ref is None: raise exception.NotFound(_('Consumer not found')) return consumer_ref def get_consumer_with_secret(self, consumer_id): session = sql.get_session() consumer_ref = self._get_consumer(session, consumer_id) return consumer_ref.to_dict() def get_consumer(self, consumer_id): return core.filter_consumer( self.get_consumer_with_secret(consumer_id)) def create_consumer(self, consumer): consumer['secret'] = uuid.uuid4().hex if not consumer.get('description'): consumer['description'] = None session = sql.get_session() with session.begin(): consumer_ref = Consumer.from_dict(consumer) session.add(consumer_ref) return consumer_ref.to_dict() def _delete_consumer(self, session, consumer_id): consumer_ref = self._get_consumer(session, consumer_id) q = session.query(Consumer) q = q.filter_by(id=consumer_id) q.delete(False) session.delete(consumer_ref) def _delete_request_tokens(self, session, consumer_id): q = session.query(RequestToken) req_tokens = q.filter_by(consumer_id=consumer_id) req_tokens_list = set([x.id for x in req_tokens]) for token_id in req_tokens_list: token_ref = self._get_request_token(session, token_id) q = session.query(RequestToken) q = q.filter_by(id=token_id) q.delete(False) session.delete(token_ref) def _delete_access_tokens(self, session, consumer_id): q = session.query(AccessToken) acc_tokens = q.filter_by(consumer_id=consumer_id) acc_tokens_list = set([x.id for x in acc_tokens]) for token_id in acc_tokens_list: token_ref = self._get_access_token(session, token_id) q = session.query(AccessToken) q = q.filter_by(id=token_id) q.delete(False) session.delete(token_ref) def delete_consumer(self, consumer_id): session = sql.get_session() with session.begin(): self._delete_request_tokens(session, consumer_id) self._delete_access_tokens(session, consumer_id) self._delete_consumer(session, consumer_id) def list_consumers(self): session = sql.get_session() cons = session.query(Consumer) return [core.filter_consumer(x.to_dict()) for x in cons] def update_consumer(self, consumer_id, consumer): session = sql.get_session() with session.begin(): consumer_ref = self._get_consumer(session, consumer_id) old_consumer_dict = consumer_ref.to_dict() old_consumer_dict.update(consumer) new_consumer = Consumer.from_dict(old_consumer_dict) consumer_ref.description = new_consumer.description consumer_ref.extra = new_consumer.extra return core.filter_consumer(consumer_ref.to_dict()) def create_request_token(self, consumer_id, project_id, token_duration, request_token_id=None, request_token_secret=None): if request_token_id is None: request_token_id = uuid.uuid4().hex if request_token_secret is None: request_token_secret = uuid.uuid4().hex expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.isotime(future, subsecond=True) ref = {} ref['id'] = request_token_id ref['request_secret'] = request_token_secret ref['verifier'] = None ref['authorizing_user_id'] = None ref['requested_project_id'] = project_id ref['role_ids'] = None ref['consumer_id'] = consumer_id ref['expires_at'] = expiry_date session = sql.get_session() with session.begin(): token_ref = RequestToken.from_dict(ref) session.add(token_ref) return token_ref.to_dict() def _get_request_token(self, session, request_token_id): token_ref = session.query(RequestToken).get(request_token_id) if token_ref is None: raise exception.NotFound(_('Request token not found')) return token_ref def get_request_token(self, request_token_id): session = sql.get_session() token_ref = self._get_request_token(session, request_token_id) return token_ref.to_dict() def authorize_request_token(self, request_token_id, user_id, role_ids): session = sql.get_session() with session.begin(): token_ref = self._get_request_token(session, request_token_id) token_dict = token_ref.to_dict() token_dict['authorizing_user_id'] = user_id token_dict['verifier'] = str(random.randint(1000, 9999)) token_dict['role_ids'] = jsonutils.dumps(role_ids) new_token = RequestToken.from_dict(token_dict) for attr in RequestToken.attributes: if (attr == 'authorizing_user_id' or attr == 'verifier' or attr == 'role_ids'): setattr(token_ref, attr, getattr(new_token, attr)) return token_ref.to_dict() def create_access_token(self, request_token_id, token_duration, access_token_id=None, access_token_secret=None): if access_token_id is None: access_token_id = uuid.uuid4().hex if access_token_secret is None: access_token_secret = uuid.uuid4().hex session = sql.get_session() with session.begin(): req_token_ref = self._get_request_token(session, request_token_id) token_dict = req_token_ref.to_dict() expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.isotime(future, subsecond=True) # add Access Token ref = {} ref['id'] = access_token_id ref['access_secret'] = access_token_secret ref['authorizing_user_id'] = token_dict['authorizing_user_id'] ref['project_id'] = token_dict['requested_project_id'] ref['role_ids'] = token_dict['role_ids'] ref['consumer_id'] = token_dict['consumer_id'] ref['expires_at'] = expiry_date token_ref = AccessToken.from_dict(ref) session.add(token_ref) # remove request token, it's been used q = session.query(RequestToken) q = q.filter_by(id=request_token_id) q.delete(False) session.delete(req_token_ref) return token_ref.to_dict() def _get_access_token(self, session, access_token_id): token_ref = session.query(AccessToken).get(access_token_id) if token_ref is None: raise exception.NotFound(_('Access token not found')) return token_ref def get_access_token(self, access_token_id): session = sql.get_session() token_ref = self._get_access_token(session, access_token_id) return token_ref.to_dict() def list_access_tokens(self, user_id): session = sql.get_session() q = session.query(AccessToken) user_auths = q.filter_by(authorizing_user_id=user_id) return [core.filter_token(x.to_dict()) for x in user_auths] def delete_access_token(self, user_id, access_token_id): session = sql.get_session() with session.begin(): token_ref = self._get_access_token(session, access_token_id) token_dict = token_ref.to_dict() if token_dict['authorizing_user_id'] != user_id: raise exception.Unauthorized(_('User IDs do not match')) q = session.query(AccessToken) q = q.filter_by(id=access_token_id) q.delete(False) session.delete(token_ref) keystone-2014.1/keystone/contrib/oauth1/backends/__init__.py0000664000175400017540000000000012323716267025164 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/migrate_repo/0000775000175400017540000000000012323716511023760 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/migrate_repo/versions/0000775000175400017540000000000012323716511025630 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/migrate_repo/versions/002_fix_oauth_tables_fk.py0000664000175400017540000000415512323716267032600 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql from keystone.common.sql import migration_helpers def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine consumer_table = sql.Table('consumer', meta, autoload=True) request_token_table = sql.Table('request_token', meta, autoload=True) access_token_table = sql.Table('access_token', meta, autoload=True) constraints = [{'table': request_token_table, 'fk_column': 'consumer_id', 'ref_column': consumer_table.c.id}, {'table': access_token_table, 'fk_column': 'consumer_id', 'ref_column': consumer_table.c.id}] if meta.bind != 'sqlite': migration_helpers.add_constraints(constraints) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine consumer_table = sql.Table('consumer', meta, autoload=True) request_token_table = sql.Table('request_token', meta, autoload=True) access_token_table = sql.Table('access_token', meta, autoload=True) constraints = [{'table': request_token_table, 'fk_column': 'consumer_id', 'ref_column': consumer_table.c.id}, {'table': access_token_table, 'fk_column': 'consumer_id', 'ref_column': consumer_table.c.id}] if meta.bind != 'sqlite': migration_helpers.remove_constraints(constraints) keystone-2014.1/keystone/contrib/oauth1/migrate_repo/versions/001_add_oauth_tables.py0000664000175400017540000000547112323716267032063 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine consumer_table = sql.Table( 'consumer', meta, sql.Column('id', sql.String(64), primary_key=True, nullable=False), sql.Column('description', sql.String(64), nullable=False), sql.Column('secret', sql.String(64), nullable=False), sql.Column('extra', sql.Text(), nullable=False)) consumer_table.create(migrate_engine, checkfirst=True) request_token_table = sql.Table( 'request_token', meta, sql.Column('id', sql.String(64), primary_key=True, nullable=False), sql.Column('request_secret', sql.String(64), nullable=False), sql.Column('verifier', sql.String(64), nullable=True), sql.Column('authorizing_user_id', sql.String(64), nullable=True), sql.Column('requested_project_id', sql.String(64), nullable=False), sql.Column('requested_roles', sql.Text(), nullable=False), sql.Column('consumer_id', sql.String(64), nullable=False, index=True), sql.Column('expires_at', sql.String(64), nullable=True)) request_token_table.create(migrate_engine, checkfirst=True) access_token_table = sql.Table( 'access_token', meta, sql.Column('id', sql.String(64), primary_key=True, nullable=False), sql.Column('access_secret', sql.String(64), nullable=False), sql.Column('authorizing_user_id', sql.String(64), nullable=False, index=True), sql.Column('project_id', sql.String(64), nullable=False), sql.Column('requested_roles', sql.Text(), nullable=False), sql.Column('consumer_id', sql.String(64), nullable=False), sql.Column('expires_at', sql.String(64), nullable=True)) access_token_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine # Operations to reverse the above upgrade go here. tables = ['consumer', 'request_token', 'access_token'] for table_name in tables: table = sql.Table(table_name, meta, autoload=True) table.drop() keystone-2014.1/keystone/contrib/oauth1/migrate_repo/versions/004_request_token_roles_nullable.py0000664000175400017540000000266312323716267034556 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine request_token_table = sql.Table('request_token', meta, autoload=True) request_token_table.c.requested_roles.alter(nullable=True) request_token_table.c.requested_roles.alter(name="role_ids") access_token_table = sql.Table('access_token', meta, autoload=True) access_token_table.c.requested_roles.alter(name="role_ids") def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine request_token_table = sql.Table('request_token', meta, autoload=True) request_token_table.c.role_ids.alter(nullable=False) request_token_table.c.role_ids.alter(name="requested_roles") access_token_table = sql.Table('access_token', meta, autoload=True) access_token_table.c.role_ids.alter(name="requested_roles") keystone-2014.1/keystone/contrib/oauth1/migrate_repo/versions/003_consumer_description_nullalbe.py0000664000175400017540000000176212323716267034716 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import sqlalchemy as sql def upgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine user_table = sql.Table('consumer', meta, autoload=True) user_table.c.description.alter(nullable=True) def downgrade(migrate_engine): meta = sql.MetaData() meta.bind = migrate_engine user_table = sql.Table('consumer', meta, autoload=True) user_table.c.description.alter(nullable=False) keystone-2014.1/keystone/contrib/oauth1/migrate_repo/versions/__init__.py0000664000175400017540000000000012323716267027737 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/migrate_repo/migrate.cfg0000664000175400017540000000231212323716267026077 0ustar jenkinsjenkins00000000000000[db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. repository_id=oauth1 # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. # If this is changed once a database is under version control, you'll need to # change the table name in each database too. version_table=migrate_version # When committing a change script, Migrate will attempt to generate the # sql for all supported databases; normally, if one of them fails - probably # because you don't have that database installed - it is ignored and the # commit continues, perhaps ending successfully. # Databases in this list MUST compile successfully during a commit, or the # entire commit will fail. List the databases your application will actually # be using to ensure your updates to that database work properly. # This must be a list; example: ['postgres','sqlite'] required_dbs=[] # When creating new change scripts, Migrate will stamp the new script with # a version number. By default this is latest_version + 1. You can set this # to 'true' to tell Migrate to use the UTC timestamp instead. use_timestamp_numbering=False keystone-2014.1/keystone/contrib/oauth1/migrate_repo/__init__.py0000664000175400017540000000000012323716267026067 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/oauth1/__init__.py0000664000175400017540000000120512323716272023416 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. from keystone.contrib.oauth1.core import * # flake8: noqa keystone-2014.1/keystone/contrib/s3/0000775000175400017540000000000012323716511020427 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/s3/core.py0000664000175400017540000000472012323716267021744 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Main entry point into the S3 Credentials service. This service provides S3 token validation for services configured with the s3_token middleware to authorize S3 requests. This service uses the same credentials used by EC2. Refer to the documentation for the EC2 module for how to generate the required credentials. """ import base64 import hashlib import hmac from keystone.common import extension from keystone.common import utils from keystone.common import wsgi from keystone import config from keystone.contrib.ec2 import controllers from keystone import exception CONF = config.CONF EXTENSION_DATA = { 'name': 'OpenStack S3 API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 's3tokens/v1.0', 'alias': 's3tokens', 'updated': '2013-07-07T12:00:0-00:00', 'description': 'OpenStack S3 API.', 'links': [ { 'rel': 'describedby', # TODO(ayoung): needs a description 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) class S3Extension(wsgi.ExtensionRouter): def add_routes(self, mapper): controller = S3Controller() # validation mapper.connect('/s3tokens', controller=controller, action='authenticate', conditions=dict(method=['POST'])) class S3Controller(controllers.Ec2Controller): def check_signature(self, creds_ref, credentials): msg = base64.urlsafe_b64decode(str(credentials['token'])) key = str(creds_ref['secret']) signed = base64.encodestring( hmac.new(key, msg, hashlib.sha1).digest()).strip() if not utils.auth_str_equal(credentials['signature'], signed): raise exception.Unauthorized('Credential signature mismatch') keystone-2014.1/keystone/contrib/s3/__init__.py0000664000175400017540000000120112323716272022536 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.contrib.s3.core import * keystone-2014.1/keystone/contrib/revoke/0000775000175400017540000000000012323716511021375 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/model.py0000664000175400017540000002652412323716267023070 0ustar jenkinsjenkins00000000000000# 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 keystone.openstack.common import timeutils # The set of attributes common between the RevokeEvent # and the dictionaries created from the token Data. _NAMES = ['trust_id', 'consumer_id', 'access_token_id', 'expires_at', 'domain_id', 'project_id', 'user_id', 'role_id'] # Additional arguments for creating a RevokeEvent _EVENT_ARGS = ['issued_before', 'revoked_at'] # Values that will be in the token data but not in the event. # These will compared with event values that have different names. # For example: both trustor_id and trustee_id are compared against user_id _TOKEN_KEYS = ['identity_domain_id', 'assignment_domain_id', 'issued_at', 'trustor_id', 'trustee_id'] REVOKE_KEYS = _NAMES + _EVENT_ARGS def blank_token_data(issued_at): token_data = dict() for name in _NAMES: token_data[name] = None for name in _TOKEN_KEYS: token_data[name] = None # required field token_data['issued_at'] = issued_at return token_data class RevokeEvent(object): def __init__(self, **kwargs): for k in REVOKE_KEYS: v = kwargs.get(k, None) setattr(self, k, v) if self.revoked_at is None: self.revoked_at = timeutils.utcnow() if self.issued_before is None: self.issued_before = self.revoked_at def to_dict(self): keys = ['user_id', 'role_id', 'domain_id', 'project_id'] event = dict((key, self.__dict__[key]) for key in keys if self.__dict__[key] is not None) if self.trust_id is not None: event['OS-TRUST:trust_id'] = self.trust_id if self.consumer_id is not None: event['OS-OAUTH1:consumer_id'] = self.consumer_id if self.consumer_id is not None: event['OS-OAUTH1:access_token_id'] = self.access_token_id if self.expires_at is not None: event['expires_at'] = timeutils.isotime(self.expires_at, subsecond=True) if self.issued_before is not None: event['issued_before'] = timeutils.isotime(self.issued_before, subsecond=True) return event def key_for_name(self, name): return "%s=%s" % (name, getattr(self, name) or '*') def attr_keys(event): return map(event.key_for_name, _NAMES) class RevokeTree(object): """Fast Revocation Checking Tree Structure The Tree is an index to quickly match tokens against events. Each node is a hashtable of key=value combinations from revocation events. The """ def __init__(self, revoke_events=None): self.revoke_map = dict() self.add_events(revoke_events) def add_event(self, event): """Updates the tree based on a revocation event. Creates any necessary internal nodes in the tree corresponding to the fields of the revocation event. The leaf node will always be set to the latest 'issued_before' for events that are otherwise identical. :param: Event to add to the tree :returns: the event that was passed in. """ revoke_map = self.revoke_map for key in attr_keys(event): revoke_map = revoke_map.setdefault(key, {}) revoke_map['issued_before'] = max( event.issued_before, revoke_map.get( 'issued_before', event.issued_before)) return event def remove_event(self, event): """Update the tree based on the removal of a Revocation Event Removes empty nodes from the tree from the leaf back to the root. If multiple events trace the same path, but have different 'issued_before' values, only the last is ever stored in the tree. So only an exact match on 'issued_before' ever triggers a removal :param: Event to remove from the tree """ stack = [] revoke_map = self.revoke_map for name in _NAMES: key = event.key_for_name(name) nxt = revoke_map.get(key) if nxt is None: break stack.append((revoke_map, key, nxt)) revoke_map = nxt else: if event.issued_before == revoke_map['issued_before']: revoke_map.pop('issued_before') for parent, key, child in reversed(stack): if not any(child): del parent[key] def add_events(self, revoke_events): return map(self.add_event, revoke_events or []) def is_revoked(self, token_data): """Check if a token matches the revocation event Compare the values for each level of the tree with the values from the token, accounting for attributes that have alternative keys, and for wildcard matches. if there is a match, continue down the tree. if there is no match, exit early. token_data is a map based on a flattened view of token. The required fields are: 'expires_at','user_id', 'project_id', 'identity_domain_id', 'assignment_domain_id', 'trust_id', 'trustor_id', 'trustee_id' 'consumer_id', 'access_token_id' """ # Alternative names to be checked in token for every field in # revoke tree. alternatives = { 'user_id': ['user_id', 'trustor_id', 'trustee_id'], 'domain_id': ['identity_domain_id', 'assignment_domain_id'], } # Contains current forest (collection of trees) to be checked. partial_matches = [self.revoke_map] # We iterate over every layer of our revoke tree (except the last one). for name in _NAMES: # bundle is the set of partial matches for the next level down # the tree bundle = [] wildcard = '%s=*' % (name,) # For every tree in current forest. for tree in partial_matches: # If there is wildcard node on current level we take it. bundle.append(tree.get(wildcard)) if name == 'role_id': # Roles are very special since a token has a list of them. # If the revocation event matches any one of them, # revoke the token. for role_id in token_data.get('roles', []): bundle.append(tree.get('role_id=%s' % role_id)) else: # For other fields we try to get any branch that concur # with any alternative field in the token. for alt_name in alternatives.get(name, [name]): bundle.append( tree.get('%s=%s' % (name, token_data[alt_name]))) # tree.get returns `None` if there is no match, so `bundle.append` # adds a 'None' entry. This call remoes the `None` entries. partial_matches = [x for x in bundle if x is not None] if not partial_matches: # If we end up with no branches to follow means that the token # is definitely not in the revoke tree and all further # iterations will be for nothing. return False # The last (leaf) level is checked in a special way because we verify # issued_at field differently. for leaf in partial_matches: try: if leaf['issued_before'] > token_data['issued_at']: return True except KeyError: pass # If we made it out of the loop then no element in revocation tree # corresponds to our token and it is good. return False def build_token_values_v2(access, default_domain_id): token_data = access['token'] token_values = { 'expires_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['expires'])), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at']))} token_values['user_id'] = access.get('user', {}).get('id') project = token_data.get('tenant') if project is not None: token_values['project_id'] = project['id'] else: token_values['project_id'] = None token_values['identity_domain_id'] = default_domain_id token_values['assignment_domain_id'] = default_domain_id trust = token_data.get('trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_id'] token_values['trustee_id'] = trust['trustee_id'] token_values['consumer_id'] = None token_values['access_token_id'] = None role_list = [] # Roles are by ID in metadata and by name in the user section roles = access.get('metadata', {}).get('roles', []) for role in roles: role_list.append(role) token_values['roles'] = role_list return token_values def build_token_values(token_data): token_values = { 'expires_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['expires_at'])), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at']))} user = token_data.get('user') if user is not None: token_values['user_id'] = user['id'] token_values['identity_domain_id'] = user['domain']['id'] else: token_values['user_id'] = None token_values['identity_domain_id'] = None project = token_data.get('project', token_data.get('tenant')) if project is not None: token_values['project_id'] = project['id'] token_values['assignment_domain_id'] = project['domain']['id'] else: token_values['project_id'] = None token_values['assignment_domain_id'] = None role_list = [] roles = token_data.get('roles') if roles is not None: for role in roles: role_list.append(role['id']) token_values['roles'] = role_list trust = token_data.get('OS-TRUST:trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_user']['id'] token_values['trustee_id'] = trust['trustee_user']['id'] oauth1 = token_data.get('OS-OAUTH1') if oauth1 is None: token_values['consumer_id'] = None token_values['access_token_id'] = None else: token_values['consumer_id'] = oauth1['consumer_id'] token_values['access_token_id'] = oauth1['access_token_id'] return token_values keystone-2014.1/keystone/contrib/revoke/controllers.py0000664000175400017540000000342212323716267024326 0ustar jenkinsjenkins00000000000000# 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 keystone.common import controller from keystone.common import dependency from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import timeutils @dependency.requires('revoke_api') class RevokeController(controller.V3Controller): @controller.protected() def list_revoke_events(self, context): since = context['query_string'].get('since') last_fetch = None if since: try: last_fetch = timeutils.normalize_time( timeutils.parse_isotime(since)) except ValueError: raise exception.ValidationError( message=_('invalid date format %s') % since) events = self.revoke_api.get_events(last_fetch=last_fetch) # Build the links by hand as the standard controller calls require ids response = {'events': [event.to_dict() for event in events], 'links': { 'next': None, 'self': RevokeController.base_url( context, path=context['path']) + '/events', 'previous': None} } return response keystone-2014.1/keystone/contrib/revoke/core.py0000664000175400017540000001634212323716267022715 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import abc import datetime import six from keystone.common import cache from keystone.common import dependency from keystone.common import extension from keystone.common import manager from keystone import config from keystone.contrib.revoke import model from keystone import exception from keystone import notifications from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils CONF = config.CONF LOG = log.getLogger(__name__) EXTENSION_DATA = { 'name': 'OpenStack Revoke API', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-REVOKE/v1.0', 'alias': 'OS-REVOKE', 'updated': '2014-02-24T20:51:0-00:00', 'description': 'OpenStack revoked token reporting mechanism.', 'links': [ { 'rel': 'describedby', 'type': 'text/html', 'href': ('https://github.com/openstack/identity-api/blob/master/' 'openstack-identity-api/v3/src/markdown/' 'identity-api-v3-os-revoke-ext.md'), } ]} extension.register_admin_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) extension.register_public_extension(EXTENSION_DATA['alias'], EXTENSION_DATA) SHOULD_CACHE = cache.should_cache_fn('revoke') # TODO(ayoung): migrate from the token section REVOCATION_CACHE_EXPIRATION_TIME = lambda: CONF.token.revocation_cache_time def revoked_before_cutoff_time(): expire_delta = datetime.timedelta( seconds=CONF.token.expiration + CONF.revoke.expiration_buffer) oldest = timeutils.utcnow() - expire_delta return oldest @dependency.provider('revoke_api') class Manager(manager.Manager): """Revoke API Manager. Performs common logic for recording revocations. """ def __init__(self): super(Manager, self).__init__(CONF.revoke.driver) self._register_listeners() self.model = model def _user_callback(self, service, resource_type, operation, payload): self.revoke_by_user(payload['resource_info']) def _role_callback(self, service, resource_type, operation, payload): self.revoke( model.RevokeEvent(role_id=payload['resource_info'])) def _project_callback(self, service, resource_type, operation, payload): self.revoke( model.RevokeEvent(project_id=payload['resource_info'])) def _domain_callback(self, service, resource_type, operation, payload): self.revoke( model.RevokeEvent(domain_id=payload['resource_info'])) def _trust_callback(self, service, resource_type, operation, payload): self.revoke( model.RevokeEvent(trust_id=payload['resource_info'])) def _consumer_callback(self, service, resource_type, operation, payload): self.revoke( model.RevokeEvent(consumer_id=payload['resource_info'])) def _access_token_callback(self, service, resource_type, operation, payload): self.revoke( model.RevokeEvent(access_token_id=payload['resource_info'])) def _register_listeners(self): callbacks = [ ['deleted', 'OS-TRUST:trust', self._trust_callback], ['deleted', 'OS-OAUTH1:consumer', self._consumer_callback], ['deleted', 'OS-OAUTH1:access_token', self._access_token_callback], ['deleted', 'role', self._role_callback], ['deleted', 'user', self._user_callback], ['disabled', 'user', self._user_callback], ['deleted', 'project', self._project_callback], ['disabled', 'project', self._project_callback], ['disabled', 'domain', self._domain_callback]] for cb in callbacks: notifications.register_event_callback(*cb) def revoke_by_user(self, user_id): return self.revoke(model.RevokeEvent(user_id=user_id)) def revoke_by_expiration(self, user_id, expires_at): self.revoke( model.RevokeEvent(user_id=user_id, expires_at=expires_at)) def revoke_by_grant(self, role_id, user_id=None, domain_id=None, project_id=None): self.revoke( model.RevokeEvent(user_id=user_id, role_id=role_id, domain_id=domain_id, project_id=project_id)) def revoke_by_user_and_project(self, user_id, project_id): self.revoke( model.RevokeEvent(project_id=project_id, user_id=user_id)) def revoke_by_project_role_assignment(self, project_id, role_id): self.revoke(model.RevokeEvent(project_id=project_id, role_id=role_id)) def revoke_by_domain_role_assignment(self, domain_id, role_id): self.revoke(model.RevokeEvent(domain_id=domain_id, role_id=role_id)) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=REVOCATION_CACHE_EXPIRATION_TIME) def _get_revoke_tree(self): events = self.driver.get_events() revoke_tree = model.RevokeTree(revoke_events=events) return revoke_tree def check_token(self, token_values): """Checks the values from a token against the revocation list :param token_values: dictionary of values from a token, normalized for differences between v2 and v3. The checked values are a subset of the attributes of model.TokenEvent :raises exception.TokenNotFound: if the token is invalid """ if self._get_revoke_tree().is_revoked(token_values): raise exception.TokenNotFound(_('Failed to validate token')) def revoke(self, event): self.driver.revoke(event) self._get_revoke_tree.invalidate(self) @six.add_metaclass(abc.ABCMeta) class Driver(object): """Interface for recording and reporting revocation events.""" @abc.abstractmethod def get_events(self, last_fetch=None): """return the revocation events, as a list of objects :param last_fetch: Time of last fetch. Return all events newer. :returns: A list of keystone.contrib.revoke.model.RevokeEvent newer than `last_fetch.` If no last_fetch is specified, returns all events for tokens issued after the expiration cutoff. """ raise exception.NotImplemented() @abc.abstractmethod def revoke(self, event): """register a revocation event :param event: An instance of keystone.contrib.revoke.model.RevocationEvent """ raise exception.NotImplemented() keystone-2014.1/keystone/contrib/revoke/routers.py0000664000175400017540000000176612323716267023474 0ustar jenkinsjenkins00000000000000# 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 keystone.common import wsgi from keystone.contrib.revoke import controllers class RevokeExtension(wsgi.ExtensionRouter): PATH_PREFIX = '/OS-REVOKE' def add_routes(self, mapper): revoke_controller = controllers.RevokeController() mapper.connect(self.PATH_PREFIX + '/events', controller=revoke_controller, action='list_revoke_events', conditions=dict(method=['GET'])) keystone-2014.1/keystone/contrib/revoke/backends/0000775000175400017540000000000012323716511023147 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/backends/sql.py0000664000175400017540000001040312323716272024322 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import uuid from keystone.common import config from keystone.common import sql from keystone.contrib import revoke from keystone.contrib.revoke import model CONF = config.CONF class RevocationEvent(sql.ModelBase, sql.ModelDictMixin): __tablename__ = 'revocation_event' attributes = model.REVOKE_KEYS # The id field is not going to be exposed to the outside world. # It is, however, necessary for SQLAlchemy. id = sql.Column(sql.String(64), primary_key=True) domain_id = sql.Column(sql.String(64)) project_id = sql.Column(sql.String(64)) user_id = sql.Column(sql.String(64)) role_id = sql.Column(sql.String(64)) trust_id = sql.Column(sql.String(64)) consumer_id = sql.Column(sql.String(64)) access_token_id = sql.Column(sql.String(64)) issued_before = sql.Column(sql.DateTime(), nullable=False) expires_at = sql.Column(sql.DateTime()) revoked_at = sql.Column(sql.DateTime(), nullable=False) class Revoke(revoke.Driver): def _flush_batch_size(self, dialect): batch_size = 0 if dialect == 'ibm_db_sa': # This functionality is limited to DB2, because # it is necessary to prevent the transaction log # from filling up, whereas at least some of the # other supported databases do not support update # queries with LIMIT subqueries nor do they appear # to require the use of such queries when deleting # large numbers of records at once. batch_size = 100 # Limit of 100 is known to not fill a transaction log # of default maximum size while not significantly # impacting the performance of large token purges on # systems where the maximum transaction log size has # been increased beyond the default. return batch_size def _prune_expired_events(self): oldest = revoke.revoked_before_cutoff_time() session = sql.get_session() dialect = session.bind.dialect.name batch_size = self._flush_batch_size(dialect) if batch_size > 0: query = session.query(RevocationEvent.id) query = query.filter(RevocationEvent.revoked_at < oldest) query = query.limit(batch_size).subquery() delete_query = (session.query(RevocationEvent). filter(RevocationEvent.id.in_(query))) while True: rowcount = delete_query.delete(synchronize_session=False) if rowcount == 0: break else: query = session.query(RevocationEvent) query = query.filter(RevocationEvent.revoked_at < oldest) query.delete(synchronize_session=False) session.flush() def get_events(self, last_fetch=None): self._prune_expired_events() session = sql.get_session() query = session.query(RevocationEvent).order_by( RevocationEvent.revoked_at) if last_fetch: query.filter(RevocationEvent.revoked_at >= last_fetch) # While the query filter should handle this, it does not # appear to be working. It might be a SQLite artifact. events = [model.RevokeEvent(**e.to_dict()) for e in query if e.revoked_at > last_fetch] else: events = [model.RevokeEvent(**e.to_dict()) for e in query] return events def revoke(self, event): kwargs = dict() for attr in model.REVOKE_KEYS: kwargs[attr] = getattr(event, attr) kwargs['id'] = uuid.uuid4().hex record = RevocationEvent(**kwargs) session = sql.get_session() with session.begin(): session.add(record) keystone-2014.1/keystone/contrib/revoke/backends/kvs.py0000664000175400017540000000444212323716267024340 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import datetime from keystone.common import kvs from keystone import config from keystone.contrib import revoke from keystone import exception from keystone.openstack.common import timeutils CONF = config.CONF _EVENT_KEY = 'os-revoke-events' _KVS_BACKEND = 'openstack.kvs.Memory' class Revoke(revoke.Driver): def __init__(self, **kwargs): super(Revoke, self).__init__() self._store = kvs.get_key_value_store('os-revoke-driver') self._store.configure(backing_store=_KVS_BACKEND, **kwargs) def _get_event(self): try: return self._store.get(_EVENT_KEY) except exception.NotFound: return [] def _prune_expired_events_and_get(self, last_fetch=None, new_event=None): pruned = [] results = [] expire_delta = datetime.timedelta(seconds=CONF.token.expiration) oldest = timeutils.utcnow() - expire_delta # TODO(ayoung): Store the time of the oldest event so that the # prune process can be skipped if none of the events have timed out. with self._store.get_lock(_EVENT_KEY) as lock: events = self._get_event() if new_event is not None: events.append(new_event) for event in events: revoked_at = event.revoked_at if revoked_at > oldest: pruned.append(event) if last_fetch is None or revoked_at > last_fetch: results.append(event) self._store.set(_EVENT_KEY, pruned, lock) return results def get_events(self, last_fetch=None): return self._prune_expired_events_and_get(last_fetch=last_fetch) def revoke(self, event): self._prune_expired_events_and_get(new_event=event) keystone-2014.1/keystone/contrib/revoke/backends/__init__.py0000664000175400017540000000000012323716267025256 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/migrate_repo/0000775000175400017540000000000012323716511024052 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/migrate_repo/versions/0000775000175400017540000000000012323716511025722 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py0000664000175400017540000000341512323716267031331 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sqlalchemy as sql def upgrade(migrate_engine): # Upgrade operations go here. Don't create your own engine; bind # migrate_engine to your metadata meta = sql.MetaData() meta.bind = migrate_engine service_table = sql.Table( 'revocation_event', meta, sql.Column('id', sql.String(64), primary_key=True), sql.Column('domain_id', sql.String(64)), sql.Column('project_id', sql.String(64)), sql.Column('user_id', sql.String(64)), sql.Column('role_id', sql.String(64)), sql.Column('trust_id', sql.String(64)), sql.Column('consumer_id', sql.String(64)), sql.Column('access_token_id', sql.String(64)), sql.Column('issued_before', sql.DateTime(), nullable=False), sql.Column('expires_at', sql.DateTime()), sql.Column('revoked_at', sql.DateTime(), index=True, nullable=False)) service_table.create(migrate_engine, checkfirst=True) def downgrade(migrate_engine): # Operations to reverse the above upgrade go here. meta = sql.MetaData() meta.bind = migrate_engine tables = ['revocation_event'] for t in tables: table = sql.Table(t, meta, autoload=True) table.drop(migrate_engine, checkfirst=True) keystone-2014.1/keystone/contrib/revoke/migrate_repo/versions/__init__.py0000664000175400017540000000000012323716267030031 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/migrate_repo/migrate.cfg0000664000175400017540000000231212323716267026171 0ustar jenkinsjenkins00000000000000[db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. repository_id=revoke # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. # If this is changed once a database is under version control, you'll need to # change the table name in each database too. version_table=migrate_version # When committing a change script, Migrate will attempt to generate the # sql for all supported databases; normally, if one of them fails - probably # because you don't have that database installed - it is ignored and the # commit continues, perhaps ending successfully. # Databases in this list MUST compile successfully during a commit, or the # entire commit will fail. List the databases your application will actually # be using to ensure your updates to that database work properly. # This must be a list; example: ['postgres','sqlite'] required_dbs=[] # When creating new change scripts, Migrate will stamp the new script with # a version number. By default this is latest_version + 1. You can set this # to 'true' to tell Migrate to use the UTC timestamp instead. use_timestamp_numbering=False keystone-2014.1/keystone/contrib/revoke/migrate_repo/__init__.py0000664000175400017540000000000012323716267026161 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/revoke/__init__.py0000664000175400017540000000113512323716272023512 0ustar jenkinsjenkins00000000000000# 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 keystone.contrib.revoke.core import * # flake8: noqa keystone-2014.1/keystone/contrib/admin_crud/0000775000175400017540000000000012323716511022207 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/contrib/admin_crud/core.py0000664000175400017540000002045512323716267023527 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone import assignment from keystone import catalog from keystone.common import extension from keystone.common import wsgi from keystone import identity extension.register_admin_extension( 'OS-KSADM', { 'name': 'OpenStack Keystone Admin', 'namespace': 'http://docs.openstack.org/identity/api/ext/' 'OS-KSADM/v1.0', 'alias': 'OS-KSADM', 'updated': '2013-07-11T17:14:00-00:00', 'description': 'OpenStack extensions to Keystone v2.0 API ' 'enabling Administrative Operations.', 'links': [ { 'rel': 'describedby', # TODO(dolph): link needs to be revised after # bug 928059 merges 'type': 'text/html', 'href': 'https://github.com/openstack/identity-api', } ]}) class CrudExtension(wsgi.ExtensionRouter): """Previously known as the OS-KSADM extension. Provides a bunch of CRUD operations for internal data types. """ def add_routes(self, mapper): tenant_controller = assignment.controllers.Tenant() user_controller = identity.controllers.User() role_controller = assignment.controllers.Role() service_controller = catalog.controllers.Service() endpoint_controller = catalog.controllers.Endpoint() # Tenant Operations mapper.connect( '/tenants', controller=tenant_controller, action='create_project', conditions=dict(method=['POST'])) mapper.connect( '/tenants/{tenant_id}', controller=tenant_controller, action='update_project', conditions=dict(method=['PUT', 'POST'])) mapper.connect( '/tenants/{tenant_id}', controller=tenant_controller, action='delete_project', conditions=dict(method=['DELETE'])) mapper.connect( '/tenants/{tenant_id}/users', controller=tenant_controller, action='get_project_users', conditions=dict(method=['GET'])) # User Operations mapper.connect( '/users', controller=user_controller, action='get_users', conditions=dict(method=['GET'])) mapper.connect( '/users', controller=user_controller, action='create_user', conditions=dict(method=['POST'])) # NOTE(termie): not in diablo mapper.connect( '/users/{user_id}', controller=user_controller, action='update_user', conditions=dict(method=['PUT'])) mapper.connect( '/users/{user_id}', controller=user_controller, action='delete_user', conditions=dict(method=['DELETE'])) # COMPAT(diablo): the copy with no OS-KSADM is from diablo mapper.connect( '/users/{user_id}/password', controller=user_controller, action='set_user_password', conditions=dict(method=['PUT'])) mapper.connect( '/users/{user_id}/OS-KSADM/password', controller=user_controller, action='set_user_password', conditions=dict(method=['PUT'])) # COMPAT(diablo): the copy with no OS-KSADM is from diablo mapper.connect( '/users/{user_id}/tenant', controller=user_controller, action='update_user', conditions=dict(method=['PUT'])) mapper.connect( '/users/{user_id}/OS-KSADM/tenant', controller=user_controller, action='update_user', conditions=dict(method=['PUT'])) # COMPAT(diablo): the copy with no OS-KSADM is from diablo mapper.connect( '/users/{user_id}/enabled', controller=user_controller, action='set_user_enabled', conditions=dict(method=['PUT'])) mapper.connect( '/users/{user_id}/OS-KSADM/enabled', controller=user_controller, action='set_user_enabled', conditions=dict(method=['PUT'])) # User Roles mapper.connect( '/users/{user_id}/roles/OS-KSADM/{role_id}', controller=role_controller, action='add_role_to_user', conditions=dict(method=['PUT'])) mapper.connect( '/users/{user_id}/roles/OS-KSADM/{role_id}', controller=role_controller, action='remove_role_from_user', conditions=dict(method=['DELETE'])) # COMPAT(diablo): User Roles mapper.connect( '/users/{user_id}/roleRefs', controller=role_controller, action='get_role_refs', conditions=dict(method=['GET'])) mapper.connect( '/users/{user_id}/roleRefs', controller=role_controller, action='create_role_ref', conditions=dict(method=['POST'])) mapper.connect( '/users/{user_id}/roleRefs/{role_ref_id}', controller=role_controller, action='delete_role_ref', conditions=dict(method=['DELETE'])) # User-Tenant Roles mapper.connect( '/tenants/{tenant_id}/users/{user_id}/roles/OS-KSADM/{role_id}', controller=role_controller, action='add_role_to_user', conditions=dict(method=['PUT'])) mapper.connect( '/tenants/{tenant_id}/users/{user_id}/roles/OS-KSADM/{role_id}', controller=role_controller, action='remove_role_from_user', conditions=dict(method=['DELETE'])) # Service Operations mapper.connect( '/OS-KSADM/services', controller=service_controller, action='get_services', conditions=dict(method=['GET'])) mapper.connect( '/OS-KSADM/services', controller=service_controller, action='create_service', conditions=dict(method=['POST'])) mapper.connect( '/OS-KSADM/services/{service_id}', controller=service_controller, action='delete_service', conditions=dict(method=['DELETE'])) mapper.connect( '/OS-KSADM/services/{service_id}', controller=service_controller, action='get_service', conditions=dict(method=['GET'])) # Endpoint Templates mapper.connect( '/endpoints', controller=endpoint_controller, action='get_endpoints', conditions=dict(method=['GET'])) mapper.connect( '/endpoints', controller=endpoint_controller, action='create_endpoint', conditions=dict(method=['POST'])) mapper.connect( '/endpoints/{endpoint_id}', controller=endpoint_controller, action='delete_endpoint', conditions=dict(method=['DELETE'])) # Role Operations mapper.connect( '/OS-KSADM/roles', controller=role_controller, action='create_role', conditions=dict(method=['POST'])) mapper.connect( '/OS-KSADM/roles', controller=role_controller, action='get_roles', conditions=dict(method=['GET'])) mapper.connect( '/OS-KSADM/roles/{role_id}', controller=role_controller, action='get_role', conditions=dict(method=['GET'])) mapper.connect( '/OS-KSADM/roles/{role_id}', controller=role_controller, action='delete_role', conditions=dict(method=['DELETE'])) keystone-2014.1/keystone/contrib/admin_crud/__init__.py0000664000175400017540000000121112323716272024317 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.contrib.admin_crud.core import * keystone-2014.1/keystone/contrib/__init__.py0000664000175400017540000000000012323716267022211 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/trust/0000775000175400017540000000000012323716511017623 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/trust/controllers.py0000664000175400017540000002366412323716272022562 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import uuid import six from keystone import assignment from keystone.common import controller from keystone.common import dependency from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import timeutils LOG = log.getLogger(__name__) CONF = config.CONF def _trustor_only(context, trust, user_id): if user_id != trust.get('trustor_user_id'): raise exception.Forbidden() def _trustor_trustee_only(trust, user_id): if (user_id != trust.get('trustee_user_id') and user_id != trust.get('trustor_user_id')): raise exception.Forbidden() def _admin_trustor_only(context, trust, user_id): if user_id != trust.get('trustor_user_id') and not context['is_admin']: raise exception.Forbidden() @dependency.requires('assignment_api', 'identity_api', 'trust_api', 'token_api') class TrustV3(controller.V3Controller): collection_name = "trusts" member_name = "trust" @classmethod def base_url(cls, context, path=None): """Construct a path and pass it to V3Controller.base_url method.""" # NOTE(stevemar): Overriding path to /OS-TRUST/trusts so that # V3Controller.base_url handles setting the self link correctly. path = '/OS-TRUST/' + cls.collection_name return super(TrustV3, cls).base_url(context, path=path) def _get_user_id(self, context): if 'token_id' in context: token_id = context['token_id'] token = self.token_api.get_token(token_id) user_id = token['user']['id'] return user_id return None def get_trust(self, context, trust_id): user_id = self._get_user_id(context) trust = self.trust_api.get_trust(trust_id) if not trust: raise exception.TrustNotFound(trust_id) _trustor_trustee_only(trust, user_id) self._fill_in_roles(context, trust, self.assignment_api.list_roles()) return TrustV3.wrap_member(context, trust) def _fill_in_roles(self, context, trust, all_roles): if trust.get('expires_at') is not None: trust['expires_at'] = (timeutils.isotime (trust['expires_at'], subsecond=True)) if 'roles' not in trust: trust['roles'] = [] trust_full_roles = [] for trust_role in trust['roles']: if isinstance(trust_role, six.string_types): trust_role = {'id': trust_role} matching_roles = [x for x in all_roles if x['id'] == trust_role['id']] if matching_roles: full_role = assignment.controllers.RoleV3.wrap_member( context, matching_roles[0])['role'] trust_full_roles.append(full_role) trust['roles'] = trust_full_roles trust['roles_links'] = { 'self': (self.base_url(context) + "/%s/roles" % trust['id']), 'next': None, 'previous': None} def _clean_role_list(self, context, trust, all_roles): trust_roles = [] all_role_names = dict((r['name'], r) for r in all_roles) for role in trust.get('roles', []): if 'id' in role: trust_roles.append({'id': role['id']}) elif 'name' in role: rolename = role['name'] if rolename in all_role_names: trust_roles.append({'id': all_role_names[rolename]['id']}) else: raise exception.RoleNotFound("role %s is not defined" % rolename) else: raise exception.ValidationError(attribute='id or name', target='roles') return trust_roles @controller.protected() def create_trust(self, context, trust=None): """Create a new trust. The user creating the trust must be the trustor. """ # TODO(ayoung): instead of raising ValidationError on the first # problem, return a collection of all the problems. if not trust: raise exception.ValidationError(attribute='trust', target='request') if trust.get('project_id') and not trust.get('roles'): raise exception.Forbidden( _('At least one role should be specified.')) try: user_id = self._get_user_id(context) _trustor_only(context, trust, user_id) #confirm that the trustee exists self.identity_api.get_user(trust['trustee_user_id']) all_roles = self.assignment_api.list_roles() clean_roles = self._clean_role_list(context, trust, all_roles) if trust.get('project_id'): user_role = self.assignment_api.get_roles_for_user_and_project( user_id, trust['project_id']) else: user_role = [] for trust_role in clean_roles: matching_roles = [x for x in user_role if x == trust_role['id']] if not matching_roles: raise exception.RoleNotFound(role_id=trust_role['id']) if trust.get('expires_at') is not None: if not trust['expires_at'].endswith('Z'): trust['expires_at'] += 'Z' try: trust['expires_at'] = (timeutils.parse_isotime (trust['expires_at'])) except ValueError: raise exception.ValidationTimeStampError() trust_id = uuid.uuid4().hex new_trust = self.trust_api.create_trust(trust_id, trust, clean_roles) self._fill_in_roles(context, new_trust, all_roles) return TrustV3.wrap_member(context, new_trust) except KeyError as e: raise exception.ValidationError(attribute=e.args[0], target='trust') @controller.protected() def list_trusts(self, context): query = context['query_string'] trusts = [] if not query: self.assert_admin(context) trusts += self.trust_api.list_trusts() if 'trustor_user_id' in query: user_id = query['trustor_user_id'] calling_user_id = self._get_user_id(context) if user_id != calling_user_id: raise exception.Forbidden() trusts += (self.trust_api. list_trusts_for_trustor(user_id)) if 'trustee_user_id' in query: user_id = query['trustee_user_id'] calling_user_id = self._get_user_id(context) if user_id != calling_user_id: raise exception.Forbidden() trusts += self.trust_api.list_trusts_for_trustee(user_id) for trust in trusts: # get_trust returns roles, list_trusts does not # It seems in some circumstances, roles does not # exist in the query response, so check first if 'roles' in trust: del trust['roles'] if trust.get('expires_at') is not None: trust['expires_at'] = (timeutils.isotime (trust['expires_at'], subsecond=True)) return TrustV3.wrap_collection(context, trusts) @controller.protected() def delete_trust(self, context, trust_id): trust = self.trust_api.get_trust(trust_id) if not trust: raise exception.TrustNotFound(trust_id) user_id = self._get_user_id(context) _admin_trustor_only(context, trust, user_id) self.trust_api.delete_trust(trust_id) userid = trust['trustor_user_id'] self.token_api.delete_tokens(userid, trust_id=trust_id) @controller.protected() def list_roles_for_trust(self, context, trust_id): trust = self.get_trust(context, trust_id)['trust'] if not trust: raise exception.TrustNotFound(trust_id) user_id = self._get_user_id(context) _trustor_trustee_only(trust, user_id) return {'roles': trust['roles'], 'links': trust['roles_links']} @controller.protected() def check_role_for_trust(self, context, trust_id, role_id): """Checks if a role has been assigned to a trust.""" trust = self.trust_api.get_trust(trust_id) if not trust: raise exception.TrustNotFound(trust_id) user_id = self._get_user_id(context) _trustor_trustee_only(trust, user_id) if not any(role['id'] == role_id for role in trust['roles']): raise exception.RoleNotFound(role_id=role_id) @controller.protected() def get_role_for_trust(self, context, trust_id, role_id): """Get a role that has been assigned to a trust.""" self.check_role_for_trust(context, trust_id, role_id) role = self.assignment_api.get_role(role_id) return assignment.controllers.RoleV3.wrap_member(context, role) keystone-2014.1/keystone/trust/core.py0000664000175400017540000000624212323716267021141 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Main entry point into the Identity service.""" import abc import six from keystone.common import dependency from keystone.common import manager from keystone import config from keystone import exception from keystone import notifications from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) @dependency.provider('trust_api') class Manager(manager.Manager): """Default pivot point for the Trust backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. """ _TRUST = "OS-TRUST:trust" def __init__(self): super(Manager, self).__init__(CONF.trust.driver) @notifications.created(_TRUST) def create_trust(self, trust_id, trust, roles): """Create a new trust. :returns: a new trust """ trust.setdefault('remaining_uses', None) if trust['remaining_uses'] is not None: if (trust['remaining_uses'] <= 0 or not isinstance(trust['remaining_uses'], int)): msg = _('remaining_uses must be a positive integer or null.') raise exception.ValidationError(msg) return self.driver.create_trust(trust_id, trust, roles) @notifications.deleted(_TRUST) def delete_trust(self, trust_id): """Remove a trust. :raises: keystone.exception.TrustNotFound """ self.driver.delete_trust(trust_id) @six.add_metaclass(abc.ABCMeta) class Driver(object): @abc.abstractmethod def create_trust(self, trust_id, trust, roles): """Create a new trust. :returns: a new trust """ raise exception.NotImplemented() @abc.abstractmethod def get_trust(self, trust_id): raise exception.NotImplemented() @abc.abstractmethod def list_trusts(self): raise exception.NotImplemented() @abc.abstractmethod def list_trusts_for_trustee(self, trustee): raise exception.NotImplemented() @abc.abstractmethod def list_trusts_for_trustor(self, trustor): raise exception.NotImplemented() @abc.abstractmethod def delete_trust(self, trust_id): raise exception.NotImplemented() @abc.abstractmethod def consume_use(self, trust_id): """Consume one use when a trust was created with a limitation on its uses, provided there are still uses available. :raises: keystone.exception.TrustUseLimitReached, keystone.exception.TrustNotFound """ raise exception.NotImplemented() keystone-2014.1/keystone/trust/routers.py0000664000175400017540000000414312323716267021712 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """WSGI Routers for the Identity service.""" from keystone.trust import controllers def append_v3_routers(mapper, routers): trust_controller = controllers.TrustV3() mapper.connect('/OS-TRUST/trusts', controller=trust_controller, action='create_trust', conditions=dict(method=['POST'])) mapper.connect('/OS-TRUST/trusts', controller=trust_controller, action='list_trusts', conditions=dict(method=['GET'])) mapper.connect('/OS-TRUST/trusts/{trust_id}', controller=trust_controller, action='delete_trust', conditions=dict(method=['DELETE'])) mapper.connect('/OS-TRUST/trusts/{trust_id}', controller=trust_controller, action='get_trust', conditions=dict(method=['GET'])) mapper.connect('/OS-TRUST/trusts/{trust_id}/roles', controller=trust_controller, action='list_roles_for_trust', conditions=dict(method=['GET'])) mapper.connect('/OS-TRUST/trusts/{trust_id}/roles/{role_id}', controller=trust_controller, action='check_role_for_trust', conditions=dict(method=['HEAD'])) mapper.connect('/OS-TRUST/trusts/{trust_id}/roles/{role_id}', controller=trust_controller, action='get_role_for_trust', conditions=dict(method=['GET'])) keystone-2014.1/keystone/trust/backends/0000775000175400017540000000000012323716511021375 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/trust/backends/sql.py0000664000175400017540000001271012323716272022553 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import sql from keystone import exception from keystone.openstack.common import timeutils from keystone import trust class TrustModel(sql.ModelBase, sql.DictBase): __tablename__ = 'trust' attributes = ['id', 'trustor_user_id', 'trustee_user_id', 'project_id', 'impersonation', 'expires_at', 'remaining_uses'] id = sql.Column(sql.String(64), primary_key=True) #user id Of owner trustor_user_id = sql.Column(sql.String(64), nullable=False,) #user_id of user allowed to consume this preauth trustee_user_id = sql.Column(sql.String(64), nullable=False) project_id = sql.Column(sql.String(64)) impersonation = sql.Column(sql.Boolean, nullable=False) deleted_at = sql.Column(sql.DateTime) expires_at = sql.Column(sql.DateTime) remaining_uses = sql.Column(sql.Integer, nullable=True) extra = sql.Column(sql.JsonBlob()) class TrustRole(sql.ModelBase): __tablename__ = 'trust_role' attributes = ['trust_id', 'role_id'] trust_id = sql.Column(sql.String(64), primary_key=True, nullable=False) role_id = sql.Column(sql.String(64), primary_key=True, nullable=False) class Trust(trust.Driver): @sql.handle_conflicts(conflict_type='trust') def create_trust(self, trust_id, trust, roles): session = sql.get_session() with session.begin(): ref = TrustModel.from_dict(trust) ref['id'] = trust_id if ref.get('expires_at') and ref['expires_at'].tzinfo is not None: ref['expires_at'] = timeutils.normalize_time(ref['expires_at']) session.add(ref) added_roles = [] for role in roles: trust_role = TrustRole() trust_role.trust_id = trust_id trust_role.role_id = role['id'] added_roles.append({'id': role['id']}) session.add(trust_role) trust_dict = ref.to_dict() trust_dict['roles'] = added_roles return trust_dict def _add_roles(self, trust_id, session, trust_dict): roles = [] for role in session.query(TrustRole).filter_by(trust_id=trust_id): roles.append({'id': role.role_id}) trust_dict['roles'] = roles @sql.handle_conflicts(conflict_type='trust') def consume_use(self, trust_id): session = sql.get_session() with session.begin(): ref = (session.query(TrustModel). with_lockmode('update'). filter_by(deleted_at=None). filter_by(id=trust_id).first()) if ref is None: raise exception.TrustNotFound(trust_id=trust_id) if ref.remaining_uses is None: # unlimited uses, do nothing pass elif ref.remaining_uses > 0: ref.remaining_uses -= 1 else: raise exception.TrustUseLimitReached(trust_id=trust_id) def get_trust(self, trust_id): session = sql.get_session() ref = (session.query(TrustModel). filter_by(deleted_at=None). filter_by(id=trust_id).first()) if ref is None: return None if ref.expires_at is not None: now = timeutils.utcnow() if now > ref.expires_at: return None # Do not return trusts that can't be used anymore if ref.remaining_uses is not None: if ref.remaining_uses <= 0: return None trust_dict = ref.to_dict() self._add_roles(trust_id, session, trust_dict) return trust_dict @sql.handle_conflicts(conflict_type='trust') def list_trusts(self): session = sql.get_session() trusts = session.query(TrustModel).filter_by(deleted_at=None) return [trust_ref.to_dict() for trust_ref in trusts] @sql.handle_conflicts(conflict_type='trust') def list_trusts_for_trustee(self, trustee_user_id): session = sql.get_session() trusts = (session.query(TrustModel). filter_by(deleted_at=None). filter_by(trustee_user_id=trustee_user_id)) return [trust_ref.to_dict() for trust_ref in trusts] @sql.handle_conflicts(conflict_type='trust') def list_trusts_for_trustor(self, trustor_user_id): session = sql.get_session() trusts = (session.query(TrustModel). filter_by(deleted_at=None). filter_by(trustor_user_id=trustor_user_id)) return [trust_ref.to_dict() for trust_ref in trusts] @sql.handle_conflicts(conflict_type='trust') def delete_trust(self, trust_id): session = sql.get_session() with session.begin(): trust_ref = session.query(TrustModel).get(trust_id) if not trust_ref: raise exception.TrustNotFound(trust_id=trust_id) trust_ref.deleted_at = timeutils.utcnow() keystone-2014.1/keystone/trust/backends/kvs.py0000664000175400017540000000762612323716267022575 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """ An in memory implementation of the trusts API. only to be used for testing purposes """ import copy from keystone.common import kvs from keystone import exception from keystone.openstack.common import timeutils from keystone import trust def _filter_trust(ref): if ref['deleted']: return None if ref.get('expires_at') and timeutils.utcnow() > ref['expires_at']: return None remaining_uses = ref.get('remaining_uses') # Do not return trusts that can't be used anymore if remaining_uses is not None: if remaining_uses <= 0: return None ref = copy.deepcopy(ref) return ref class Trust(kvs.Base, trust.Driver): def create_trust(self, trust_id, trust, roles): trust_ref = copy.deepcopy(trust) trust_ref['id'] = trust_id trust_ref['deleted'] = False trust_ref['roles'] = roles if (trust_ref.get('expires_at') and trust_ref['expires_at'].tzinfo is not None): trust_ref['expires_at'] = (timeutils.normalize_time (trust_ref['expires_at'])) self.db.set('trust-%s' % trust_id, trust_ref) trustee_user_id = trust_ref['trustee_user_id'] trustee_list = self.db.get('trustee-%s' % trustee_user_id, []) trustee_list.append(trust_id) self.db.set('trustee-%s' % trustee_user_id, trustee_list) trustor_user_id = trust_ref['trustor_user_id'] trustor_list = self.db.get('trustor-%s' % trustor_user_id, []) trustor_list.append(trust_id) self.db.set('trustor-%s' % trustor_user_id, trustor_list) return trust_ref def consume_use(self, trust_id): try: orig_ref = self.db.get('trust-%s' % trust_id) except exception.NotFound: raise exception.TrustNotFound(trust_id=trust_id) remaining_uses = orig_ref.get('remaining_uses') if remaining_uses is None: # unlimited uses, do nothing return elif remaining_uses > 0: ref = copy.deepcopy(orig_ref) ref['remaining_uses'] -= 1 self.db.set('trust-%s' % trust_id, ref) else: raise exception.TrustUseLimitReached(trust_id=trust_id) def get_trust(self, trust_id): try: ref = self.db.get('trust-%s' % trust_id) return _filter_trust(ref) except exception.NotFound: return None def delete_trust(self, trust_id): try: ref = self.db.get('trust-%s' % trust_id) except exception.NotFound: raise exception.TrustNotFound(trust_id=trust_id) ref['deleted'] = True self.db.set('trust-%s' % trust_id, ref) def list_trusts(self): trusts = [] for key, value in self.db.items(): if key.startswith("trust-") and not value['deleted']: trusts.append(value) return trusts def list_trusts_for_trustee(self, trustee_user_id): trusts = [] for trust in self.db.get('trustee-%s' % trustee_user_id, []): trusts.append(self.get_trust(trust)) return trusts def list_trusts_for_trustor(self, trustor_user_id): trusts = [] for trust in self.db.get('trustor-%s' % trustor_user_id, []): trusts.append(self.get_trust(trust)) return trusts keystone-2014.1/keystone/trust/backends/__init__.py0000664000175400017540000000000012323716267023504 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/trust/__init__.py0000664000175400017540000000130612323716272021740 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.trust import controllers from keystone.trust.core import * from keystone.trust import routers keystone-2014.1/keystone/exception.py0000664000175400017540000002572412323716272021030 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import six from keystone.common import config from keystone.openstack.common.gettextutils import _ # flake8: noqa from keystone.openstack.common import log from keystone.openstack.common import strutils CONF = config.CONF LOG = log.getLogger(__name__) # Tests use this to make exception message format errors fatal _FATAL_EXCEPTION_FORMAT_ERRORS = False class Error(Exception): """Base error class. Child classes should define an HTTP status code, title, and a message_format. """ code = None title = None message_format = None def __init__(self, message=None, **kwargs): try: message = self._build_message(message, **kwargs) except KeyError: # if you see this warning in your logs, please raise a bug report if _FATAL_EXCEPTION_FORMAT_ERRORS: raise else: LOG.warning(_('missing exception kwargs (programmer error)')) message = self.message_format super(Error, self).__init__(message) def _build_message(self, message, **kwargs): """Builds and returns an exception message. :raises: KeyError given insufficient kwargs """ if not message: try: message = self.message_format % kwargs except UnicodeDecodeError: try: kwargs = dict([(k, strutils.safe_decode(v)) for k, v in six.iteritems(kwargs)]) except UnicodeDecodeError: # NOTE(jamielennox): This is the complete failure case # at least by showing the template we have some idea # of where the error is coming from message = self.message_format else: message = self.message_format % kwargs return message class ValidationError(Error): message_format = _("Expecting to find %(attribute)s in %(target)s." " The server could not comply with the request" " since it is either malformed or otherwise" " incorrect. The client is assumed to be in error.") code = 400 title = 'Bad Request' class ValidationTimeStampError(Error): message_format = _("Timestamp not in expected format." " The server could not comply with the request" " since it is either malformed or otherwise" " incorrect. The client is assumed to be in error.") code = 400 title = 'Bad Request' class StringLengthExceeded(ValidationError): message_format = _("String length exceeded.The length of" " string '%(string)s' exceeded the limit" " of column %(type)s(CHAR(%(length)d)).") class ValidationSizeError(Error): message_format = _("Request attribute %(attribute)s must be" " less than or equal to %(size)i. The server" " could not comply with the request because" " the attribute size is invalid (too large)." " The client is assumed to be in error.") code = 400 title = 'Bad Request' class PKITokenExpected(Error): message_format = _('The certificates you requested are not available. ' 'It is likely that this server does not use PKI tokens ' 'otherwise this is the result of misconfiguration.') code = 403 title = 'Cannot retrieve certificates' class SecurityError(Error): """Avoids exposing details of security failures, unless in debug mode.""" def _build_message(self, message, **kwargs): """Only returns detailed messages in debug mode.""" if CONF.debug: return message or self.message_format % kwargs else: return self.message_format % kwargs class Unauthorized(SecurityError): message_format = _("The request you have made requires authentication.") code = 401 title = 'Unauthorized' class AuthPluginException(Unauthorized): message_format = _("Authentication plugin error.") def __init__(self, *args, **kwargs): super(AuthPluginException, self).__init__(*args, **kwargs) self.authentication = {} class MissingGroups(Unauthorized): message_format = _("Unable to find valid groups while using " "mapping %(mapping_id)s") class AuthMethodNotSupported(AuthPluginException): message_format = _("Attempted to authenticate with an unsupported method.") def __init__(self, *args, **kwargs): super(AuthMethodNotSupported, self).__init__(*args, **kwargs) self.authentication = {'methods': CONF.auth.methods} class AdditionalAuthRequired(AuthPluginException): message_format = _("Additional authentications steps required.") def __init__(self, auth_response=None, **kwargs): super(AdditionalAuthRequired, self).__init__(message=None, **kwargs) self.authentication = auth_response class Forbidden(SecurityError): message_format = _("You are not authorized to perform the" " requested action.") code = 403 title = 'Forbidden' class ForbiddenAction(Forbidden): message_format = _("You are not authorized to perform the" " requested action, %(action)s.") class ImmutableAttributeError(Forbidden): message_format = _("Could not change immutable attribute %(attribute)s" " in target %(target)s") class NotFound(Error): message_format = _("Could not find, %(target)s.") code = 404 title = 'Not Found' class EndpointNotFound(NotFound): message_format = _("Could not find endpoint, %(endpoint_id)s.") class MetadataNotFound(NotFound): """(dolph): metadata is not a user-facing concept, so this exception should not be exposed """ message_format = _("An unhandled exception has occurred:" " Could not find metadata.") class PolicyNotFound(NotFound): message_format = _("Could not find policy, %(policy_id)s.") class RoleNotFound(NotFound): message_format = _("Could not find role, %(role_id)s.") class RegionNotFound(NotFound): message_format = _("Could not find region, %(region_id)s.") class ServiceNotFound(NotFound): message_format = _("Could not find service, %(service_id)s.") class DomainNotFound(NotFound): message_format = _("Could not find domain, %(domain_id)s.") class ProjectNotFound(NotFound): message_format = _("Could not find project, %(project_id)s.") class TokenNotFound(NotFound): message_format = _("Could not find token, %(token_id)s.") class UserNotFound(NotFound): message_format = _("Could not find user, %(user_id)s.") class GroupNotFound(NotFound): message_format = _("Could not find group, %(group_id)s.") class MappingNotFound(NotFound): message_format = _("Could not find mapping, %(mapping_id)s.") class TrustNotFound(NotFound): message_format = _("Could not find trust, %(trust_id)s.") class TrustUseLimitReached(Forbidden): message_format = _("No remaining uses for trust %(trust_id)s.") class CredentialNotFound(NotFound): message_format = _("Could not find credential, %(credential_id)s.") class VersionNotFound(NotFound): message_format = _("Could not find version, %(version)s.") class IdentityProviderNotFound(NotFound): message_format = _("Could not find IdentityProvider, %(idp_id)s.") class FederatedProtocolNotFound(NotFound): message_format = _("Could not find federated protocol %(protocol_id)s for" " IdentityProvider, %(idp_id)s") class Conflict(Error): message_format = _("Conflict occurred attempting to store %(type)s." " %(details)s") code = 409 title = 'Conflict' class RequestTooLarge(Error): message_format = _("Request is too large.") code = 413 title = 'Request is too large.' class UnexpectedError(SecurityError): """Avoids exposing details of failures, unless in debug mode.""" _message_format = _("An unexpected error prevented the server " "from fulfilling your request.") debug_message_format = _("An unexpected error prevented the server " "from fulfilling your request. %(exception)s") @property def message_format(self): """Return the generic message format string unless debug is enabled.""" if CONF.debug: return self.debug_message_format return self._message_format def _build_message(self, message, **kwargs): if CONF.debug and 'exception' not in kwargs: # Ensure that exception has a value to be extra defensive for # substitutions and make sure the exception doesn't raise an # exception. kwargs['exception'] = '' return super(UnexpectedError, self)._build_message(message, **kwargs) code = 500 title = 'Internal Server Error' class CertificateFilesUnavailable(UnexpectedError): debug_message_format = _("Expected signing certificates are not available " "on the server. Please check Keystone " "configuration.") class MalformedEndpoint(UnexpectedError): debug_message_format = _("Malformed endpoint URL (%(endpoint)s)," " see ERROR log for details.") class MappedGroupNotFound(UnexpectedError): debug_message_format = _("Group %(group_id)s returned by mapping " "%(mapping_id)s was not found in the backend.") class NotImplemented(Error): message_format = _("The action you have requested has not" " been implemented.") code = 501 title = 'Not Implemented' class Gone(Error): message_format = _("The service you have requested is no" " longer available on this server.") code = 410 title = 'Gone' class ConfigFileNotFound(UnexpectedError): debug_message_format = _("The Keystone configuration file %(config_file)s " "could not be found.") class MigrationNotProvided(Exception): def __init__(self, mod_name, path): super(MigrationNotProvided, self).__init__(_( "%(mod_name)s doesn't provide database migrations. The migration" " repository path at %(path)s doesn't exist or isn't a directory." ) % {'mod_name': mod_name, 'path': path}) keystone-2014.1/keystone/assignment/0000775000175400017540000000000012323716511020612 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/assignment/controllers.py0000664000175400017540000010505612323716267023551 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, Inc. # Copyright 2012 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. """Workflow Logic the Assignment service.""" import copy import uuid import six from six.moves import urllib from keystone.common import controller from keystone.common import dependency from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) @dependency.requires('assignment_api', 'identity_api', 'token_api') class Tenant(controller.V2Controller): @controller.v2_deprecated def get_all_projects(self, context, **kw): """Gets a list of all tenants for an admin user.""" if 'name' in context['query_string']: return self.get_project_by_name( context, context['query_string'].get('name')) self.assert_admin(context) tenant_refs = self.assignment_api.list_projects_in_domain( CONF.identity.default_domain_id) for tenant_ref in tenant_refs: tenant_ref = self.filter_domain_id(tenant_ref) params = { 'limit': context['query_string'].get('limit'), 'marker': context['query_string'].get('marker'), } return self._format_project_list(tenant_refs, **params) @controller.v2_deprecated def get_projects_for_token(self, context, **kw): """Get valid tenants for token based on token used to authenticate. Pulls the token from the context, validates it and gets the valid tenants for the user in the token. Doesn't care about token scopedness. """ try: token_ref = self.token_api.get_token(context['token_id']) except exception.NotFound as e: LOG.warning(_('Authentication failed: %s'), e) raise exception.Unauthorized(e) user_ref = token_ref['user'] tenant_refs = ( self.assignment_api.list_projects_for_user(user_ref['id'])) tenant_refs = [self.filter_domain_id(ref) for ref in tenant_refs if ref['domain_id'] == CONF.identity.default_domain_id] params = { 'limit': context['query_string'].get('limit'), 'marker': context['query_string'].get('marker'), } return self._format_project_list(tenant_refs, **params) @controller.v2_deprecated def get_project(self, context, tenant_id): # TODO(termie): this stuff should probably be moved to middleware self.assert_admin(context) ref = self.assignment_api.get_project(tenant_id) return {'tenant': self.filter_domain_id(ref)} @controller.v2_deprecated def get_project_by_name(self, context, tenant_name): self.assert_admin(context) ref = self.assignment_api.get_project_by_name( tenant_name, CONF.identity.default_domain_id) return {'tenant': self.filter_domain_id(ref)} # CRUD Extension @controller.v2_deprecated def create_project(self, context, tenant): tenant_ref = self._normalize_dict(tenant) if 'name' not in tenant_ref or not tenant_ref['name']: msg = _('Name field is required and cannot be empty') raise exception.ValidationError(message=msg) self.assert_admin(context) tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex) tenant = self.assignment_api.create_project( tenant_ref['id'], self._normalize_domain_id(context, tenant_ref)) return {'tenant': self.filter_domain_id(tenant)} @controller.v2_deprecated def update_project(self, context, tenant_id, tenant): self.assert_admin(context) # Remove domain_id if specified - a v2 api caller should not # be specifying that clean_tenant = tenant.copy() clean_tenant.pop('domain_id', None) tenant_ref = self.assignment_api.update_project( tenant_id, clean_tenant) return {'tenant': tenant_ref} @controller.v2_deprecated def delete_project(self, context, tenant_id): self.assert_admin(context) self.assignment_api.delete_project(tenant_id) @controller.v2_deprecated def get_project_users(self, context, tenant_id, **kw): self.assert_admin(context) user_refs = [] user_ids = self.assignment_api.list_user_ids_for_project(tenant_id) for user_id in user_ids: try: user_ref = self.identity_api.get_user(user_id) except exception.UserNotFound: # Log that user is missing and continue on. message = _("User %(user_id)s in project %(project_id)s " "doesn't exist.") LOG.debug(message, {'user_id': user_id, 'project_id': tenant_id}) else: user_refs.append(self.v3_to_v2_user(user_ref)) return {'users': user_refs} def _format_project_list(self, tenant_refs, **kwargs): marker = kwargs.get('marker') first_index = 0 if marker is not None: for (marker_index, tenant) in enumerate(tenant_refs): if tenant['id'] == marker: # we start pagination after the marker first_index = marker_index + 1 break else: msg = _('Marker could not be found') raise exception.ValidationError(message=msg) limit = kwargs.get('limit') last_index = None if limit is not None: try: limit = int(limit) if limit < 0: raise AssertionError() except (ValueError, AssertionError): msg = _('Invalid limit value') raise exception.ValidationError(message=msg) last_index = first_index + limit tenant_refs = tenant_refs[first_index:last_index] for x in tenant_refs: if 'enabled' not in x: x['enabled'] = True o = {'tenants': tenant_refs, 'tenants_links': []} return o @dependency.requires('assignment_api') class Role(controller.V2Controller): # COMPAT(essex-3) @controller.v2_deprecated def get_user_roles(self, context, user_id, tenant_id=None): """Get the roles for a user and tenant pair. Since we're trying to ignore the idea of user-only roles we're not implementing them in hopes that the idea will die off. """ self.assert_admin(context) if tenant_id is None: raise exception.NotImplemented(message='User roles not supported: ' 'tenant ID required') roles = self.assignment_api.get_roles_for_user_and_project( user_id, tenant_id) return {'roles': [self.assignment_api.get_role(x) for x in roles]} # CRUD extension @controller.v2_deprecated def get_role(self, context, role_id): self.assert_admin(context) return {'role': self.assignment_api.get_role(role_id)} @controller.v2_deprecated def create_role(self, context, role): role = self._normalize_dict(role) self.assert_admin(context) if 'name' not in role or not role['name']: msg = _('Name field is required and cannot be empty') raise exception.ValidationError(message=msg) role_id = uuid.uuid4().hex role['id'] = role_id role_ref = self.assignment_api.create_role(role_id, role) return {'role': role_ref} @controller.v2_deprecated def delete_role(self, context, role_id): self.assert_admin(context) self.assignment_api.delete_role(role_id) @controller.v2_deprecated def get_roles(self, context): self.assert_admin(context) return {'roles': self.assignment_api.list_roles()} @controller.v2_deprecated def add_role_to_user(self, context, user_id, role_id, tenant_id=None): """Add a role to a user and tenant pair. Since we're trying to ignore the idea of user-only roles we're not implementing them in hopes that the idea will die off. """ self.assert_admin(context) if tenant_id is None: raise exception.NotImplemented(message='User roles not supported: ' 'tenant_id required') self.assignment_api.add_role_to_user_and_project( user_id, tenant_id, role_id) role_ref = self.assignment_api.get_role(role_id) return {'role': role_ref} @controller.v2_deprecated def remove_role_from_user(self, context, user_id, role_id, tenant_id=None): """Remove a role from a user and tenant pair. Since we're trying to ignore the idea of user-only roles we're not implementing them in hopes that the idea will die off. """ self.assert_admin(context) if tenant_id is None: raise exception.NotImplemented(message='User roles not supported: ' 'tenant_id required') # This still has the weird legacy semantics that adding a role to # a user also adds them to a tenant, so we must follow up on that self.assignment_api.remove_role_from_user_and_project( user_id, tenant_id, role_id) # COMPAT(diablo): CRUD extension @controller.v2_deprecated def get_role_refs(self, context, user_id): """Ultimate hack to get around having to make role_refs first-class. This will basically iterate over the various roles the user has in all tenants the user is a member of and create fake role_refs where the id encodes the user-tenant-role information so we can look up the appropriate data when we need to delete them. """ self.assert_admin(context) tenants = self.assignment_api.list_projects_for_user(user_id) o = [] for tenant in tenants: # As a v2 call, we should limit the response to those projects in # the default domain. if tenant['domain_id'] != CONF.identity.default_domain_id: continue role_ids = self.assignment_api.get_roles_for_user_and_project( user_id, tenant['id']) for role_id in role_ids: ref = {'roleId': role_id, 'tenantId': tenant['id'], 'userId': user_id} ref['id'] = urllib.parse.urlencode(ref) o.append(ref) return {'roles': o} # COMPAT(diablo): CRUD extension @controller.v2_deprecated def create_role_ref(self, context, user_id, role): """This is actually used for adding a user to a tenant. In the legacy data model adding a user to a tenant required setting a role. """ self.assert_admin(context) # TODO(termie): for now we're ignoring the actual role tenant_id = role.get('tenantId') role_id = role.get('roleId') self.assignment_api.add_role_to_user_and_project( user_id, tenant_id, role_id) role_ref = self.assignment_api.get_role(role_id) return {'role': role_ref} # COMPAT(diablo): CRUD extension @controller.v2_deprecated def delete_role_ref(self, context, user_id, role_ref_id): """This is actually used for deleting a user from a tenant. In the legacy data model removing a user from a tenant required deleting a role. To emulate this, we encode the tenant and role in the role_ref_id, and if this happens to be the last role for the user-tenant pair, we remove the user from the tenant. """ self.assert_admin(context) # TODO(termie): for now we're ignoring the actual role role_ref_ref = urllib.parse.parse_qs(role_ref_id) tenant_id = role_ref_ref.get('tenantId')[0] role_id = role_ref_ref.get('roleId')[0] self.assignment_api.remove_role_from_user_and_project( user_id, tenant_id, role_id) @dependency.requires('assignment_api') class DomainV3(controller.V3Controller): collection_name = 'domains' member_name = 'domain' def __init__(self): super(DomainV3, self).__init__() self.get_member_from_driver = self.assignment_api.get_domain @controller.protected() def create_domain(self, context, domain): self._require_attribute(domain, 'name') ref = self._assign_unique_id(self._normalize_dict(domain)) ref = self.assignment_api.create_domain(ref['id'], ref) return DomainV3.wrap_member(context, ref) @controller.filterprotected('enabled', 'name') def list_domains(self, context, filters): hints = DomainV3.build_driver_hints(context, filters) refs = self.assignment_api.list_domains(hints=hints) return DomainV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_domain(self, context, domain_id): ref = self.assignment_api.get_domain(domain_id) return DomainV3.wrap_member(context, ref) @controller.protected() def update_domain(self, context, domain_id, domain): self._require_matching_id(domain_id, domain) ref = self.assignment_api.update_domain(domain_id, domain) return DomainV3.wrap_member(context, ref) @controller.protected() def delete_domain(self, context, domain_id): return self.assignment_api.delete_domain(domain_id) @dependency.requires('assignment_api') class ProjectV3(controller.V3Controller): collection_name = 'projects' member_name = 'project' def __init__(self): super(ProjectV3, self).__init__() self.get_member_from_driver = self.assignment_api.get_project @controller.protected() def create_project(self, context, project): self._require_attribute(project, 'name') ref = self._assign_unique_id(self._normalize_dict(project)) ref = self._normalize_domain_id(context, ref) ref = self.assignment_api.create_project(ref['id'], ref) return ProjectV3.wrap_member(context, ref) @controller.filterprotected('domain_id', 'enabled', 'name') def list_projects(self, context, filters): hints = ProjectV3.build_driver_hints(context, filters) refs = self.assignment_api.list_projects(hints=hints) return ProjectV3.wrap_collection(context, refs, hints=hints) @controller.filterprotected('enabled', 'name') def list_user_projects(self, context, filters, user_id): hints = ProjectV3.build_driver_hints(context, filters) refs = self.assignment_api.list_projects_for_user(user_id, hints=hints) return ProjectV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_project(self, context, project_id): ref = self.assignment_api.get_project(project_id) return ProjectV3.wrap_member(context, ref) @controller.protected() def update_project(self, context, project_id, project): self._require_matching_id(project_id, project) self._require_matching_domain_id( project_id, project, self.assignment_api.get_project) ref = self.assignment_api.update_project(project_id, project) return ProjectV3.wrap_member(context, ref) @controller.protected() def delete_project(self, context, project_id): return self.assignment_api.delete_project(project_id) @dependency.requires('assignment_api', 'identity_api') class RoleV3(controller.V3Controller): collection_name = 'roles' member_name = 'role' def __init__(self): super(RoleV3, self).__init__() self.get_member_from_driver = self.assignment_api.get_role @controller.protected() def create_role(self, context, role): self._require_attribute(role, 'name') ref = self._assign_unique_id(self._normalize_dict(role)) ref = self.assignment_api.create_role(ref['id'], ref) return RoleV3.wrap_member(context, ref) @controller.filterprotected('name') def list_roles(self, context, filters): hints = RoleV3.build_driver_hints(context, filters) refs = self.assignment_api.list_roles( hints=hints) return RoleV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_role(self, context, role_id): ref = self.assignment_api.get_role(role_id) return RoleV3.wrap_member(context, ref) @controller.protected() def update_role(self, context, role_id, role): self._require_matching_id(role_id, role) ref = self.assignment_api.update_role(role_id, role) return RoleV3.wrap_member(context, ref) @controller.protected() def delete_role(self, context, role_id): self.assignment_api.delete_role(role_id) def _require_domain_xor_project(self, domain_id, project_id): if (domain_id and project_id) or (not domain_id and not project_id): msg = _('Specify a domain or project, not both') raise exception.ValidationError(msg) def _require_user_xor_group(self, user_id, group_id): if (user_id and group_id) or (not user_id and not group_id): msg = _('Specify a user or group, not both') raise exception.ValidationError(msg) def _check_if_inherited(self, context): return (CONF.os_inherit.enabled and context['path'].startswith('/OS-INHERIT') and context['path'].endswith('/inherited_to_projects')) def _check_grant_protection(self, context, protection, role_id=None, user_id=None, group_id=None, domain_id=None, project_id=None): """Check protection for role grant APIs. The policy rule might want to inspect attributes of any of the entities involved in the grant. So we get these and pass them to the check_protection() handler in the controller. """ ref = {} if role_id: ref['role'] = self.assignment_api.get_role(role_id) if user_id: ref['user'] = self.identity_api.get_user(user_id) else: ref['group'] = self.identity_api.get_group(group_id) if domain_id: ref['domain'] = self.assignment_api.get_domain(domain_id) else: ref['project'] = self.assignment_api.get_project(project_id) self.check_protection(context, protection, ref) @controller.protected(callback=_check_grant_protection) def create_grant(self, context, role_id, user_id=None, group_id=None, domain_id=None, project_id=None): """Grants a role to a user or group on either a domain or project.""" self._require_domain_xor_project(domain_id, project_id) self._require_user_xor_group(user_id, group_id) self.assignment_api.create_grant( role_id, user_id, group_id, domain_id, project_id, self._check_if_inherited(context)) @controller.protected(callback=_check_grant_protection) def list_grants(self, context, user_id=None, group_id=None, domain_id=None, project_id=None): """Lists roles granted to user/group on either a domain or project.""" self._require_domain_xor_project(domain_id, project_id) self._require_user_xor_group(user_id, group_id) refs = self.assignment_api.list_grants( user_id, group_id, domain_id, project_id, self._check_if_inherited(context)) return RoleV3.wrap_collection(context, refs) @controller.protected(callback=_check_grant_protection) def check_grant(self, context, role_id, user_id=None, group_id=None, domain_id=None, project_id=None): """Checks if a role has been granted on either a domain or project.""" self._require_domain_xor_project(domain_id, project_id) self._require_user_xor_group(user_id, group_id) self.assignment_api.get_grant( role_id, user_id, group_id, domain_id, project_id, self._check_if_inherited(context)) @controller.protected(callback=_check_grant_protection) def revoke_grant(self, context, role_id, user_id=None, group_id=None, domain_id=None, project_id=None): """Revokes a role from user/group on either a domain or project.""" self._require_domain_xor_project(domain_id, project_id) self._require_user_xor_group(user_id, group_id) self.assignment_api.delete_grant( role_id, user_id, group_id, domain_id, project_id, self._check_if_inherited(context)) @dependency.requires('assignment_api', 'identity_api') class RoleAssignmentV3(controller.V3Controller): # TODO(henry-nash): The current implementation does not provide a full # first class entity for role-assignment. There is no role_assignment_id # and only the list_role_assignment call is supported. Further, since it # is not a first class entity, the links for the individual entities # reference the individual role grant APIs. collection_name = 'role_assignments' member_name = 'role_assignment' @classmethod def wrap_member(cls, context, ref): # NOTE(henry-nash): Since we are not yet a true collection, we override # the wrapper as have already included the links in the entities pass def _format_entity(self, context, entity): """Format an assignment entity for API response. The driver layer returns entities as dicts containing the ids of the actor (e.g. user or group), target (e.g. domain or project) and role. If it is an inherited role, then this is also indicated. Examples: {'user_id': user_id, 'project_id': domain_id, 'role_id': role_id} or, for an inherited role: {'user_id': user_id, 'domain_id': domain_id, 'role_id': role_id, 'inherited_to_projects': true} This function maps this into the format to be returned via the API, e.g. for the second example above: { 'user': { {'id': user_id} }, 'scope': { 'domain': { {'id': domain_id} }, 'OS-INHERIT:inherited_to': 'projects }, 'role': { {'id': role_id} }, 'links': { 'assignment': '/domains/domain_id/users/user_id/roles/' 'role_id/inherited_to_projects' } } """ formatted_entity = {} suffix = "" if 'user_id' in entity: formatted_entity['user'] = {'id': entity['user_id']} actor_link = 'users/%s' % entity['user_id'] if 'group_id' in entity: formatted_entity['group'] = {'id': entity['group_id']} actor_link = 'groups/%s' % entity['group_id'] if 'role_id' in entity: formatted_entity['role'] = {'id': entity['role_id']} if 'project_id' in entity: formatted_entity['scope'] = ( {'project': {'id': entity['project_id']}}) target_link = '/projects/%s' % entity['project_id'] if 'domain_id' in entity: formatted_entity['scope'] = ( {'domain': {'id': entity['domain_id']}}) if 'inherited_to_projects' in entity: formatted_entity['scope']['OS-INHERIT:inherited_to'] = ( 'projects') target_link = '/OS-INHERIT/domains/%s' % entity['domain_id'] suffix = '/inherited_to_projects' else: target_link = '/domains/%s' % entity['domain_id'] formatted_entity.setdefault('links', {}) path = '%(target)s/%(actor)s/roles/%(role)s%(suffix)s' % { 'target': target_link, 'actor': actor_link, 'role': entity['role_id'], 'suffix': suffix} formatted_entity['links']['assignment'] = self.base_url(context, path) return formatted_entity def _expand_indirect_assignments(self, context, refs): """Processes entity list into all-direct assignments. For any group role assignments in the list, create a role assignment entity for each member of that group, and then remove the group assignment entity itself from the list. If the OS-INHERIT extension is enabled, then honor any inherited roles on the domain by creating the equivalent on all projects owned by the domain. For any new entity created by virtue of group membership, add in an additional link to that membership. """ def _get_group_members(ref): """Get a list of group members. Get the list of group members. If this fails with GroupNotFound, then log this as a warning, but allow overall processing to continue. """ try: members = self.identity_api.list_users_in_group( ref['group']['id']) except exception.GroupNotFound: members = [] # The group is missing, which should not happen since # group deletion should remove any related assignments, so # log a warning if 'domain' in ref: target = 'Domain: %s' % ref['domain'].get('domain_id') elif 'project' in ref: target = 'Project: %s' % ref['project'].get('project_id') else: # Should always be a domain or project, but since to get # here things have gone astray, let's be cautious. target = 'Unknown' LOG.warning( _('Group %(group)s not found for role-assignment - ' '%(target)s with Role: %(role)s'), { 'group': ref['group_id'], 'target': target, 'role': ref.get('role_id')}) return members def _build_user_assignment_equivalent_of_group( user, group_id, template): """Create a user assignment equivalent to the group one. The template has had the 'group' entity removed, so substitute a 'user' one. The 'assignment' link stays as it is, referring to the group assignment that led to this role. A 'membership' link is added that refers to this particular user's membership of this group. """ user_entry = copy.deepcopy(template) user_entry['user'] = {'id': user['id']} user_entry['links']['membership'] = ( self.base_url(context, '/groups/%s/users/%s' % (group_id, user['id']))) return user_entry def _build_project_equivalent_of_user_domain_role( project_id, domain_id, template): """Create a user project assignment equivalent to the domain one. The template has had the 'domain' entity removed, so substitute a 'project' one, modifying the 'assignment' link to match. """ project_entry = copy.deepcopy(template) project_entry['scope']['project'] = {'id': project_id} project_entry['links']['assignment'] = ( self.base_url( context, '/OS-INHERIT/domains/%s/users/%s/roles/%s' '/inherited_to_projects' % ( domain_id, project_entry['user']['id'], project_entry['role']['id']))) return project_entry def _build_project_equivalent_of_group_domain_role( user_id, group_id, project_id, domain_id, template): """Create a user project equivalent to the domain group one. The template has had the 'domain' and 'group' entities removed, so substitute a 'user-project' one, modifying the 'assignment' link to match. """ project_entry = copy.deepcopy(template) project_entry['user'] = {'id': user_id} project_entry['scope']['project'] = {'id': project_id} project_entry['links']['assignment'] = ( self.base_url(context, '/OS-INHERIT/domains/%s/groups/%s/roles/%s' '/inherited_to_projects' % ( domain_id, group_id, project_entry['role']['id']))) project_entry['links']['membership'] = ( self.base_url(context, '/groups/%s/users/%s' % (group_id, user_id))) return project_entry # Scan the list of entities for any assignments that need to be # expanded. # # If the OS-INERIT extension is enabled, the refs lists may # contain roles to be inherited from domain to project, so expand # these as well into project equivalents # # For any regular group entries, expand these into user entries based # on membership of that group. # # Due to the potentially large expansions, rather than modify the # list we are enumerating, we build a new one as we go. # new_refs = [] for r in refs: if 'OS-INHERIT:inherited_to' in r['scope']: # It's an inherited domain role - so get the list of projects # owned by this domain. A domain scope is guaranteed since we # checked this when we built the refs list project_ids = ( [x['id'] for x in self.assignment_api.list_projects_in_domain( r['scope']['domain']['id'])]) base_entry = copy.deepcopy(r) domain_id = base_entry['scope']['domain']['id'] base_entry['scope'].pop('domain') # For each project, create an equivalent role assignment for p in project_ids: # If it's a group assignment, then create equivalent user # roles based on membership of the group if 'group' in base_entry: members = _get_group_members(base_entry) sub_entry = copy.deepcopy(base_entry) group_id = sub_entry['group']['id'] sub_entry.pop('group') for m in members: new_entry = ( _build_project_equivalent_of_group_domain_role( m['id'], group_id, p, domain_id, sub_entry)) new_refs.append(new_entry) else: new_entry = ( _build_project_equivalent_of_user_domain_role( p, domain_id, base_entry)) new_refs.append(new_entry) elif 'group' in r: # It's a non-inherited group role assignment, so get the list # of members. members = _get_group_members(r) # Now replace that group role assignment entry with an # equivalent user role assignment for each of the group members base_entry = copy.deepcopy(r) group_id = base_entry['group']['id'] base_entry.pop('group') for m in members: user_entry = _build_user_assignment_equivalent_of_group( m, group_id, base_entry) new_refs.append(user_entry) else: new_refs.append(r) return new_refs def _query_filter_is_true(self, filter_value): """Determine if bool query param is 'True'. We treat this the same way as we do for policy enforcement: {bool_param}=0 is treated as False Any other value is considered to be equivalent to True, including the absence of a value """ if (isinstance(filter_value, six.string_types) and filter_value == '0'): val = False else: val = True return val def _filter_inherited(self, entry): if ('inherited_to_projects' in entry and not CONF.os_inherit.enabled): return False else: return True @controller.filterprotected('group.id', 'role.id', 'scope.domain.id', 'scope.project.id', 'scope.OS-INHERIT:inherited_to', 'user.id') def list_role_assignments(self, context, filters): # TODO(henry-nash): This implementation uses the standard filtering # in the V3.wrap_collection. Given the large number of individual # assignments, this is pretty inefficient. An alternative would be # to pass the filters into the driver call, so that the list size is # kept a minimum. hints = self.build_driver_hints(context, filters) refs = self.assignment_api.list_role_assignments() formatted_refs = ( [self._format_entity(context, x) for x in refs if self._filter_inherited(x)]) if ('effective' in context['query_string'] and self._query_filter_is_true( context['query_string']['effective'])): formatted_refs = self._expand_indirect_assignments(context, formatted_refs) return self.wrap_collection(context, formatted_refs, hints=hints) @controller.protected() def get_role_assignment(self, context): raise exception.NotImplemented() @controller.protected() def update_role_assignment(self, context): raise exception.NotImplemented() @controller.protected() def delete_role_assignment(self, context): raise exception.NotImplemented() keystone-2014.1/keystone/assignment/core.py0000664000175400017540000011567712323716272022141 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Main entry point into the assignment service.""" import abc import six from keystone import clean from keystone.common import cache from keystone.common import dependency from keystone.common import driver_hints from keystone.common import manager from keystone import config from keystone import exception from keystone import notifications from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) SHOULD_CACHE = cache.should_cache_fn('assignment') # NOTE(blk-u): The config option is not available at import time. EXPIRATION_TIME = lambda: CONF.assignment.cache_time def calc_default_domain(): return {'description': (u'Owns users and tenants (i.e. projects)' ' available on Identity API v2.'), 'enabled': True, 'id': CONF.identity.default_domain_id, 'name': u'Default'} @dependency.provider('assignment_api') @dependency.optional('revoke_api') @dependency.requires('credential_api', 'identity_api', 'token_api') class Manager(manager.Manager): """Default pivot point for the Assignment backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. assignment.Manager() and identity.Manager() have a circular dependency. The late import works around this. The if block prevents creation of the api object by both managers. """ _PROJECT = 'project' def __init__(self): assignment_driver = CONF.assignment.driver if assignment_driver is None: identity_driver = dependency.REGISTRY['identity_api'].driver assignment_driver = identity_driver.default_assignment_driver() super(Manager, self).__init__(assignment_driver) @notifications.created(_PROJECT) def create_project(self, tenant_id, tenant): tenant = tenant.copy() tenant.setdefault('enabled', True) tenant['enabled'] = clean.project_enabled(tenant['enabled']) tenant.setdefault('description', '') ret = self.driver.create_project(tenant_id, tenant) if SHOULD_CACHE(ret): self.get_project.set(ret, self, tenant_id) self.get_project_by_name.set(ret, self, ret['name'], ret['domain_id']) return ret @notifications.disabled(_PROJECT, public=False) def _disable_project(self, tenant_id): return self.token_api.delete_tokens_for_users( self.list_user_ids_for_project(tenant_id), project_id=tenant_id) @notifications.updated(_PROJECT) def update_project(self, tenant_id, tenant): tenant = tenant.copy() if 'enabled' in tenant: tenant['enabled'] = clean.project_enabled(tenant['enabled']) if not tenant.get('enabled', True): self._disable_project(tenant_id) ret = self.driver.update_project(tenant_id, tenant) self.get_project.invalidate(self, tenant_id) self.get_project_by_name.invalidate(self, ret['name'], ret['domain_id']) return ret @notifications.deleted(_PROJECT) def delete_project(self, tenant_id): project = self.driver.get_project(tenant_id) user_ids = self.list_user_ids_for_project(tenant_id) self.token_api.delete_tokens_for_users(user_ids, project_id=tenant_id) ret = self.driver.delete_project(tenant_id) self.get_project.invalidate(self, tenant_id) self.get_project_by_name.invalidate(self, project['name'], project['domain_id']) self.credential_api.delete_credentials_for_project(tenant_id) return ret def get_roles_for_user_and_project(self, user_id, tenant_id): """Get the roles associated with a user within given project. This includes roles directly assigned to the user on the project, as well as those by virtue of group membership. If the OS-INHERIT extension is enabled, then this will also include roles inherited from the domain. :returns: a list of role ids. :raises: keystone.exception.UserNotFound, keystone.exception.ProjectNotFound """ def _get_group_project_roles(user_id, project_ref): role_list = [] group_refs = self.identity_api.list_groups_for_user(user_id) for x in group_refs: try: metadata_ref = self._get_metadata( group_id=x['id'], tenant_id=project_ref['id']) role_list += self._roles_from_role_dicts( metadata_ref.get('roles', {}), False) except exception.MetadataNotFound: # no group grant, skip pass if CONF.os_inherit.enabled: # Now get any inherited group roles for the owning domain try: metadata_ref = self._get_metadata( group_id=x['id'], domain_id=project_ref['domain_id']) role_list += self._roles_from_role_dicts( metadata_ref.get('roles', {}), True) except (exception.MetadataNotFound, exception.NotImplemented): pass return role_list def _get_user_project_roles(user_id, project_ref): role_list = [] try: metadata_ref = self._get_metadata(user_id=user_id, tenant_id=project_ref['id']) role_list = self._roles_from_role_dicts( metadata_ref.get('roles', {}), False) except exception.MetadataNotFound: pass if CONF.os_inherit.enabled: # Now get any inherited roles for the owning domain try: metadata_ref = self._get_metadata( user_id=user_id, domain_id=project_ref['domain_id']) role_list += self._roles_from_role_dicts( metadata_ref.get('roles', {}), True) except (exception.MetadataNotFound, exception.NotImplemented): pass return role_list project_ref = self.get_project(tenant_id) user_role_list = _get_user_project_roles(user_id, project_ref) group_role_list = _get_group_project_roles(user_id, project_ref) # Use set() to process the list to remove any duplicates return list(set(user_role_list + group_role_list)) def get_roles_for_user_and_domain(self, user_id, domain_id): """Get the roles associated with a user within given domain. :returns: a list of role ids. :raises: keystone.exception.UserNotFound, keystone.exception.DomainNotFound """ def _get_group_domain_roles(user_id, domain_id): role_list = [] group_refs = self.identity_api.list_groups_for_user(user_id) for x in group_refs: try: metadata_ref = self._get_metadata(group_id=x['id'], domain_id=domain_id) role_list += self._roles_from_role_dicts( metadata_ref.get('roles', {}), False) except (exception.MetadataNotFound, exception.NotImplemented): # MetadataNotFound implies no group grant, so skip. # Ignore NotImplemented since not all backends support # domains. pass return role_list def _get_user_domain_roles(user_id, domain_id): metadata_ref = {} try: metadata_ref = self._get_metadata(user_id=user_id, domain_id=domain_id) except (exception.MetadataNotFound, exception.NotImplemented): # MetadataNotFound implies no user grants. # Ignore NotImplemented since not all backends support # domains pass return self._roles_from_role_dicts( metadata_ref.get('roles', {}), False) self.get_domain(domain_id) user_role_list = _get_user_domain_roles(user_id, domain_id) group_role_list = _get_group_domain_roles(user_id, domain_id) # Use set() to process the list to remove any duplicates return list(set(user_role_list + group_role_list)) def add_user_to_project(self, tenant_id, user_id): """Add user to a tenant by creating a default role relationship. :raises: keystone.exception.ProjectNotFound, keystone.exception.UserNotFound """ try: self.driver.add_role_to_user_and_project( user_id, tenant_id, config.CONF.member_role_id) except exception.RoleNotFound: LOG.info(_("Creating the default role %s " "because it does not exist."), config.CONF.member_role_id) role = {'id': CONF.member_role_id, 'name': CONF.member_role_name} self.driver.create_role(config.CONF.member_role_id, role) #now that default role exists, the add should succeed self.driver.add_role_to_user_and_project( user_id, tenant_id, config.CONF.member_role_id) def remove_user_from_project(self, tenant_id, user_id): """Remove user from a tenant :raises: keystone.exception.ProjectNotFound, keystone.exception.UserNotFound """ roles = self.get_roles_for_user_and_project(user_id, tenant_id) if not roles: raise exception.NotFound(tenant_id) for role_id in roles: try: self.driver.remove_role_from_user_and_project(user_id, tenant_id, role_id) if self.revoke_api: self.revoke_api.revoke_by_grant(role_id, user_id=user_id, project_id=tenant_id) except exception.RoleNotFound: LOG.debug(_("Removing role %s failed because it does not " "exist."), role_id) # TODO(henry-nash): We might want to consider list limiting this at some # point in the future. def list_projects_for_user(self, user_id, hints=None): # NOTE(henry-nash): In order to get a complete list of user projects, # the driver will need to look at group assignments. To avoid cross # calling between the assignment and identity driver we get the group # list here and pass it in. The rest of the detailed logic of listing # projects for a user is pushed down into the driver to enable # optimization with the various backend technologies (SQL, LDAP etc.). group_ids = [x['id'] for x in self.identity_api.list_groups_for_user(user_id)] return self.driver.list_projects_for_user( user_id, group_ids, hints or driver_hints.Hints()) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def get_domain(self, domain_id): return self.driver.get_domain(domain_id) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def get_domain_by_name(self, domain_name): return self.driver.get_domain_by_name(domain_name) @notifications.created('domain') def create_domain(self, domain_id, domain): ret = self.driver.create_domain(domain_id, domain) if SHOULD_CACHE(ret): self.get_domain.set(ret, self, domain_id) self.get_domain_by_name.set(ret, self, ret['name']) return ret @manager.response_truncated def list_domains(self, hints=None): return self.driver.list_domains(hints or driver_hints.Hints()) @notifications.disabled('domain', public=False) def _disable_domain(self, domain_id): self.token_api.delete_tokens_for_domain(domain_id) @notifications.updated('domain') def update_domain(self, domain_id, domain): ret = self.driver.update_domain(domain_id, domain) # disable owned users & projects when the API user specifically set # enabled=False if not domain.get('enabled', True): self._disable_domain(domain_id) self.get_domain.invalidate(self, domain_id) self.get_domain_by_name.invalidate(self, ret['name']) return ret @notifications.deleted('domain') def delete_domain(self, domain_id): # explicitly forbid deleting the default domain (this should be a # carefully orchestrated manual process involving configuration # changes, etc) if domain_id == CONF.identity.default_domain_id: raise exception.ForbiddenAction(action=_('delete the default ' 'domain')) domain = self.driver.get_domain(domain_id) # To help avoid inadvertent deletes, we insist that the domain # has been previously disabled. This also prevents a user deleting # their own domain since, once it is disabled, they won't be able # to get a valid token to issue this delete. if domain['enabled']: raise exception.ForbiddenAction( action=_('cannot delete a domain that is enabled, ' 'please disable it first.')) self._delete_domain_contents(domain_id) self.driver.delete_domain(domain_id) self.get_domain.invalidate(self, domain_id) self.get_domain_by_name.invalidate(self, domain['name']) def _delete_domain_contents(self, domain_id): """Delete the contents of a domain. Before we delete a domain, we need to remove all the entities that are owned by it, i.e. Users, Groups & Projects. To do this we call the respective delete functions for these entities, which are themselves responsible for deleting any credentials and role grants associated with them as well as revoking any relevant tokens. The order we delete entities is also important since some types of backend may need to maintain referential integrity throughout, and many of the entities have relationship with each other. The following deletion order is therefore used: Projects: Reference user and groups for grants Groups: Reference users for membership and domains for grants Users: Reference domains for grants """ user_refs = self.identity_api.list_users() proj_refs = self.list_projects() group_refs = self.identity_api.list_groups() # First delete the projects themselves for project in proj_refs: if project['domain_id'] == domain_id: try: self.delete_project(project['id']) except exception.ProjectNotFound: LOG.debug(_('Project %(projectid)s not found when ' 'deleting domain contents for %(domainid)s, ' 'continuing with cleanup.'), {'projectid': project['id'], 'domainid': domain_id}) for group in group_refs: # Cleanup any existing groups. if group['domain_id'] == domain_id: try: self.identity_api.delete_group(group['id'], domain_scope=domain_id) except exception.GroupNotFound: LOG.debug(_('Group %(groupid)s not found when deleting ' 'domain contents for %(domainid)s, continuing ' 'with cleanup.'), {'groupid': group['id'], 'domainid': domain_id}) # And finally, delete the users themselves for user in user_refs: if user['domain_id'] == domain_id: try: self.identity_api.delete_user(user['id'], domain_scope=domain_id) except exception.UserNotFound: LOG.debug(_('User %(userid)s not found when ' 'deleting domain contents for %(domainid)s, ' 'continuing with cleanup.'), {'userid': user['id'], 'domainid': domain_id}) @manager.response_truncated def list_projects(self, hints=None): return self.driver.list_projects(hints or driver_hints.Hints()) # NOTE(henry-nash): list_projects_in_domain is actually an internal method # and not exposed via the API. Therefore there is no need to support # driver hints for it. def list_projects_in_domain(self, domain_id): return self.driver.list_projects_in_domain(domain_id) def list_user_projects(self, user_id, hints=None): return self.driver.list_user_projects( user_id, hints or driver_hints.Hints()) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def get_project(self, project_id): return self.driver.get_project(project_id) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def get_project_by_name(self, tenant_name, domain_id): return self.driver.get_project_by_name(tenant_name, domain_id) @cache.on_arguments(should_cache_fn=SHOULD_CACHE, expiration_time=EXPIRATION_TIME) def get_role(self, role_id): return self.driver.get_role(role_id) @notifications.created('role') def create_role(self, role_id, role): ret = self.driver.create_role(role_id, role) if SHOULD_CACHE(ret): self.get_role.set(ret, self, role_id) return ret @manager.response_truncated def list_roles(self, hints=None): return self.driver.list_roles(hints or driver_hints.Hints()) @notifications.updated('role') def update_role(self, role_id, role): ret = self.driver.update_role(role_id, role) self.get_role.invalidate(self, role_id) return ret @notifications.deleted('role') def delete_role(self, role_id): try: self._delete_tokens_for_role(role_id) except exception.NotImplemented: # FIXME(morganfainberg): Not all backends (ldap) implement # `list_role_assignments_for_role` which would have previously # caused a NotImplmented error to be raised when called through # the controller. Now error or proper action will always come from # the `delete_role` method logic. Work needs to be done to make # the behavior between drivers consistent (capable of revoking # tokens for the same circumstances). This is related to the bug # https://bugs.launchpad.net/keystone/+bug/1221805 pass self.driver.delete_role(role_id) self.get_role.invalidate(self, role_id) def list_role_assignments_for_role(self, role_id=None): # NOTE(henry-nash): Currently the efficiency of the key driver # implementation (SQL) of list_role_assignments is severely hampered by # the existence of the multiple grant tables - hence there is little # advantage in pushing the logic of this method down into the driver. # Once the single assignment table is implemented, then this situation # will be different, and this method should have its own driver # implementation. return [r for r in self.driver.list_role_assignments() if r['role_id'] == role_id] def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): self.driver.remove_role_from_user_and_project(user_id, tenant_id, role_id) if CONF.token.revoke_by_id: self.token_api.delete_tokens_for_user(user_id) if self.revoke_api: self.revoke_api.revoke_by_grant(role_id, user_id=user_id, project_id=tenant_id) def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): user_ids = [] if group_id is None: if self.revoke_api: self.revoke_api.revoke_by_grant(user_id=user_id, role_id=role_id, domain_id=domain_id, project_id=project_id) else: try: # NOTE(morganfainberg): The user ids are the important part # for invalidating tokens below, so extract them here. for user in self.identity_api.list_users_in_group(group_id, domain_id): if user['id'] != user_id: user_ids.append(user['id']) if self.revoke_api: self.revoke_api.revoke_by_grant( user_id=user['id'], role_id=role_id, domain_id=domain_id, project_id=project_id) except exception.GroupNotFound: LOG.debug(_('Group %s not found, no tokens to invalidate.'), group_id) self.driver.delete_grant(role_id, user_id, group_id, domain_id, project_id, inherited_to_projects) if user_id is not None: user_ids.append(user_id) self.token_api.delete_tokens_for_users(user_ids) def _delete_tokens_for_role(self, role_id): assignments = self.list_role_assignments_for_role(role_id=role_id) # Iterate over the assignments for this role and build the list of # user or user+project IDs for the tokens we need to delete user_ids = set() user_and_project_ids = list() for assignment in assignments: # If we have a project assignment, then record both the user and # project IDs so we can target the right token to delete. If it is # a domain assignment, we might as well kill all the tokens for # the user, since in the vast majority of cases all the tokens # for a user will be within one domain anyway, so not worth # trying to delete tokens for each project in the domain. if 'user_id' in assignment: if 'project_id' in assignment: user_and_project_ids.append( (assignment['user_id'], assignment['project_id'])) elif 'domain_id' in assignment: user_ids.add(assignment['user_id']) elif 'group_id' in assignment: # Add in any users for this group, being tolerant of any # cross-driver database integrity errors. try: users = self.identity_api.list_users_in_group( assignment['group_id']) except exception.GroupNotFound: # Ignore it, but log a debug message if 'project_id' in assignment: target = _('Project (%s)') % assignment['project_id'] elif 'domain_id' in assignment: target = _('Domain (%s)') % assignment['domain_id'] else: target = _('Unknown Target') msg = _('Group (%(group)s), referenced in assignment ' 'for %(target)s, not found - ignoring.') LOG.debug(msg, {'group': assignment['group_id'], 'target': target}) continue if 'project_id' in assignment: for user in users: user_and_project_ids.append( (user['id'], assignment['project_id'])) elif 'domain_id' in assignment: for user in users: user_ids.add(user['id']) # Now process the built up lists. Before issuing calls to delete any # tokens, let's try and minimize the number of calls by pruning out # any user+project deletions where a general token deletion for that # same user is also planned. user_and_project_ids_to_action = [] for user_and_project_id in user_and_project_ids: if user_and_project_id[0] not in user_ids: user_and_project_ids_to_action.append(user_and_project_id) self.token_api.delete_tokens_for_users(user_ids) for user_id, project_id in user_and_project_ids_to_action: self.token_api.delete_tokens_for_user(user_id, project_id) @six.add_metaclass(abc.ABCMeta) class Driver(object): def _role_to_dict(self, role_id, inherited): role_dict = {'id': role_id} if inherited: role_dict['inherited_to'] = 'projects' return role_dict def _roles_from_role_dicts(self, dict_list, inherited): role_list = [] for d in dict_list: if ((not d.get('inherited_to') and not inherited) or (d.get('inherited_to') == 'projects' and inherited)): role_list.append(d['id']) return role_list def _add_role_to_role_dicts(self, role_id, inherited, dict_list, allow_existing=True): # There is a difference in error semantics when trying to # assign a role that already exists between the coded v2 and v3 # API calls. v2 will error if the assignment already exists, # while v3 is silent. Setting the 'allow_existing' parameter # appropriately lets this call be used for both. role_set = set([frozenset(r.items()) for r in dict_list]) key = frozenset(self._role_to_dict(role_id, inherited).items()) if not allow_existing and key in role_set: raise KeyError role_set.add(key) return [dict(r) for r in role_set] def _remove_role_from_role_dicts(self, role_id, inherited, dict_list): role_set = set([frozenset(r.items()) for r in dict_list]) role_set.remove(frozenset(self._role_to_dict(role_id, inherited).items())) return [dict(r) for r in role_set] def _get_list_limit(self): return CONF.assignment.list_limit or CONF.list_limit @abc.abstractmethod def get_project_by_name(self, tenant_name, domain_id): """Get a tenant by name. :returns: tenant_ref :raises: keystone.exception.ProjectNotFound """ raise exception.NotImplemented() @abc.abstractmethod def list_user_ids_for_project(self, tenant_id): """Lists all user IDs with a role assignment in the specified project. :returns: a list of user_ids or an empty set. :raises: keystone.exception.ProjectNotFound """ raise exception.NotImplemented() @abc.abstractmethod def add_role_to_user_and_project(self, user_id, tenant_id, role_id): """Add a role to a user within given tenant. :raises: keystone.exception.UserNotFound, keystone.exception.ProjectNotFound, keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): """Remove a role from a user within given tenant. :raises: keystone.exception.UserNotFound, keystone.exception.ProjectNotFound, keystone.exception.RoleNotFound """ raise exception.NotImplemented() # assignment/grant crud @abc.abstractmethod def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): """Creates a new assignment/grant. If the assignment is to a domain, then optionally it may be specified as inherited to owned projects (this requires the OS-INHERIT extension to be enabled). :raises: keystone.exception.DomainNotFound, keystone.exception.ProjectNotFound, keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def list_grants(self, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): """Lists assignments/grants. :raises: keystone.exception.UserNotFound, keystone.exception.GroupNotFound, keystone.exception.ProjectNotFound, keystone.exception.DomainNotFound, keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def get_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): """Lists assignments/grants. :raises: keystone.exception.UserNotFound, keystone.exception.GroupNotFound, keystone.exception.ProjectNotFound, keystone.exception.DomainNotFound, keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): """Deletes assignments/grants. :raises: keystone.exception.ProjectNotFound, keystone.exception.DomainNotFound, keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def list_role_assignments(self): raise exception.NotImplemented() # domain crud @abc.abstractmethod def create_domain(self, domain_id, domain): """Creates a new domain. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_domains(self, hints): """List domains in the system. :param hints: filter hints which the driver should implement if at all possible. :returns: a list of domain_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_domain(self, domain_id): """Get a domain by ID. :returns: domain_ref :raises: keystone.exception.DomainNotFound """ raise exception.NotImplemented() @abc.abstractmethod def get_domain_by_name(self, domain_name): """Get a domain by name. :returns: domain_ref :raises: keystone.exception.DomainNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_domain(self, domain_id, domain): """Updates an existing domain. :raises: keystone.exception.DomainNotFound, keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def delete_domain(self, domain_id): """Deletes an existing domain. :raises: keystone.exception.DomainNotFound """ raise exception.NotImplemented() # project crud @abc.abstractmethod def create_project(self, project_id, project): """Creates a new project. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_projects(self, hints): """List projects in the system. :param hints: filter hints which the driver should implement if at all possible. :returns: a list of project_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def list_projects_in_domain(self, domain_id): """List projects in the domain. :param domain_id: the driver MUST only return projects within this domain. :returns: a list of project_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def list_projects_for_user(self, user_id, group_ids, hints): """List all projects associated with a given user. :param user_id: the user in question :param group_ids: the groups this user is a member of. This list is built in the Manager, so that the driver itself does not have to call across to identity. :param hints: filter hints which the driver should implement if at all possible. :returns: a list of project_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_roles_for_groups(self, group_ids, project_id=None, domain_id=None): """List all the roles assigned to groups on either domain or project. If the project_id is not None, this value will be used, no matter what was specified in the domain_id. :param group_ids: iterable with group ids :param project_id: id of the project :param domain_id: id of the domain :raises: AttributeError: In case both project_id and domain_id are set to None :returns: a list of Role entities matching groups and project_id or domain_id """ raise exception.NotImplemented() @abc.abstractmethod def list_projects_for_groups(self, group_ids): """List projects accessible to specified groups. :param group_ids: List of group ids. :returns: List of projects accessible to specified groups. """ raise exception.NotImplemented() @abc.abstractmethod def list_domains_for_groups(self, group_ids): """List domains accessible to specified groups. :param group_ids: List of group ids. :returns: List of domains accessible to specified groups. """ raise exception.NotImplemented() @abc.abstractmethod def get_project(self, project_id): """Get a project by ID. :returns: project_ref :raises: keystone.exception.ProjectNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_project(self, project_id, project): """Updates an existing project. :raises: keystone.exception.ProjectNotFound, keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def delete_project(self, project_id): """Deletes an existing project. :raises: keystone.exception.ProjectNotFound """ raise exception.NotImplemented() # role crud @abc.abstractmethod def create_role(self, role_id, role): """Creates a new role. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_roles(self, hints): """List roles in the system. :param hints: filter hints which the driver should implement if at all possible. :returns: a list of role_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_role(self, role_id): """Get a role by ID. :returns: role_ref :raises: keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_role(self, role_id, role): """Updates an existing role. :raises: keystone.exception.RoleNotFound, keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def delete_role(self, role_id): """Deletes an existing role. :raises: keystone.exception.RoleNotFound """ raise exception.NotImplemented() #TODO(ayoung): determine what else these two functions raise @abc.abstractmethod def delete_user(self, user_id): """Deletes all assignments for a user. :raises: keystone.exception.RoleNotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_group(self, group_id): """Deletes all assignments for a group. :raises: keystone.exception.RoleNotFound """ raise exception.NotImplemented() #domain management functions for backends that only allow a single domain. #currently, this is only LDAP, but might be used by PAM or other backends #as well. This is used by both identity and assignment drivers. def _set_default_domain(self, ref): """If the domain ID has not been set, set it to the default.""" if isinstance(ref, dict): if 'domain_id' not in ref: ref = ref.copy() ref['domain_id'] = CONF.identity.default_domain_id return ref elif isinstance(ref, list): return [self._set_default_domain(x) for x in ref] else: raise ValueError(_('Expected dict or list: %s') % type(ref)) def _validate_default_domain(self, ref): """Validate that either the default domain or nothing is specified. Also removes the domain from the ref so that LDAP doesn't have to persist the attribute. """ ref = ref.copy() domain_id = ref.pop('domain_id', CONF.identity.default_domain_id) self._validate_default_domain_id(domain_id) return ref def _validate_default_domain_id(self, domain_id): """Validate that the domain ID specified belongs to the default domain. """ if domain_id != CONF.identity.default_domain_id: raise exception.DomainNotFound(domain_id=domain_id) keystone-2014.1/keystone/assignment/routers.py0000664000175400017540000002113512323716267022701 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # Copyright 2013 Metacloud, Inc. # Copyright 2012 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. """WSGI Routers for the Assignment service.""" from keystone.assignment import controllers from keystone.common import router from keystone.common import wsgi from keystone import config class Public(wsgi.ComposableRouter): def add_routes(self, mapper): tenant_controller = controllers.Tenant() mapper.connect('/tenants', controller=tenant_controller, action='get_projects_for_token', conditions=dict(method=['GET'])) class Admin(wsgi.ComposableRouter): def add_routes(self, mapper): # Tenant Operations tenant_controller = controllers.Tenant() mapper.connect('/tenants', controller=tenant_controller, action='get_all_projects', conditions=dict(method=['GET'])) mapper.connect('/tenants/{tenant_id}', controller=tenant_controller, action='get_project', conditions=dict(method=['GET'])) # Role Operations roles_controller = controllers.Role() mapper.connect('/tenants/{tenant_id}/users/{user_id}/roles', controller=roles_controller, action='get_user_roles', conditions=dict(method=['GET'])) mapper.connect('/users/{user_id}/roles', controller=roles_controller, action='get_user_roles', conditions=dict(method=['GET'])) def append_v3_routers(mapper, routers): routers.append( router.Router(controllers.DomainV3(), 'domains', 'domain')) project_controller = controllers.ProjectV3() routers.append( router.Router(project_controller, 'projects', 'project')) mapper.connect('/users/{user_id}/projects', controller=project_controller, action='list_user_projects', conditions=dict(method=['GET'])) role_controller = controllers.RoleV3() routers.append(router.Router(role_controller, 'roles', 'role')) mapper.connect('/projects/{project_id}/users/{user_id}/roles/{role_id}', controller=role_controller, action='create_grant', conditions=dict(method=['PUT'])) mapper.connect('/projects/{project_id}/groups/{group_id}/roles/{role_id}', controller=role_controller, action='create_grant', conditions=dict(method=['PUT'])) mapper.connect('/projects/{project_id}/users/{user_id}/roles/{role_id}', controller=role_controller, action='check_grant', conditions=dict(method=['HEAD'])) mapper.connect('/projects/{project_id}/groups/{group_id}/roles/{role_id}', controller=role_controller, action='check_grant', conditions=dict(method=['HEAD'])) mapper.connect('/projects/{project_id}/users/{user_id}/roles', controller=role_controller, action='list_grants', conditions=dict(method=['GET'])) mapper.connect('/projects/{project_id}/groups/{group_id}/roles', controller=role_controller, action='list_grants', conditions=dict(method=['GET'])) mapper.connect('/projects/{project_id}/users/{user_id}/roles/{role_id}', controller=role_controller, action='revoke_grant', conditions=dict(method=['DELETE'])) mapper.connect('/projects/{project_id}/groups/{group_id}/roles/{role_id}', controller=role_controller, action='revoke_grant', conditions=dict(method=['DELETE'])) mapper.connect('/domains/{domain_id}/users/{user_id}/roles/{role_id}', controller=role_controller, action='create_grant', conditions=dict(method=['PUT'])) mapper.connect('/domains/{domain_id}/groups/{group_id}/roles/{role_id}', controller=role_controller, action='create_grant', conditions=dict(method=['PUT'])) mapper.connect('/domains/{domain_id}/users/{user_id}/roles/{role_id}', controller=role_controller, action='check_grant', conditions=dict(method=['HEAD'])) mapper.connect('/domains/{domain_id}/groups/{group_id}/roles/{role_id}', controller=role_controller, action='check_grant', conditions=dict(method=['HEAD'])) mapper.connect('/domains/{domain_id}/users/{user_id}/roles', controller=role_controller, action='list_grants', conditions=dict(method=['GET'])) mapper.connect('/domains/{domain_id}/groups/{group_id}/roles', controller=role_controller, action='list_grants', conditions=dict(method=['GET'])) mapper.connect('/domains/{domain_id}/users/{user_id}/roles/{role_id}', controller=role_controller, action='revoke_grant', conditions=dict(method=['DELETE'])) mapper.connect('/domains/{domain_id}/groups/{group_id}/roles/{role_id}', controller=role_controller, action='revoke_grant', conditions=dict(method=['DELETE'])) if config.CONF.os_inherit.enabled: mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}' '/roles/{role_id}/inherited_to_projects'), controller=role_controller, action='create_grant', conditions=dict(method=['PUT'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}' '/roles/{role_id}/inherited_to_projects'), controller=role_controller, action='create_grant', conditions=dict(method=['PUT'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}' '/roles/{role_id}/inherited_to_projects'), controller=role_controller, action='check_grant', conditions=dict(method=['HEAD'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}' '/roles/{role_id}/inherited_to_projects'), controller=role_controller, action='check_grant', conditions=dict(method=['HEAD'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}' '/roles/inherited_to_projects'), controller=role_controller, action='list_grants', conditions=dict(method=['GET'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}' '/roles/inherited_to_projects'), controller=role_controller, action='list_grants', conditions=dict(method=['GET'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/users/{user_id}' '/roles/{role_id}/inherited_to_projects'), controller=role_controller, action='revoke_grant', conditions=dict(method=['DELETE'])) mapper.connect(('/OS-INHERIT/domains/{domain_id}/groups/{group_id}' '/roles/{role_id}/inherited_to_projects'), controller=role_controller, action='revoke_grant', conditions=dict(method=['DELETE'])) routers.append( router.Router(controllers.RoleAssignmentV3(), 'role_assignments', 'role_assignment')) keystone-2014.1/keystone/assignment/backends/0000775000175400017540000000000012323716511022364 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/assignment/backends/sql.py0000664000175400017540000005731312323716272023552 0ustar jenkinsjenkins00000000000000# Copyright 2012-13 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. import six import sqlalchemy from keystone import assignment from keystone import clean from keystone.common import sql from keystone.common.sql import migration_helpers from keystone import config from keystone import exception from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.gettextutils import _ CONF = config.CONF class AssignmentType: USER_PROJECT = 'UserProject' GROUP_PROJECT = 'GroupProject' USER_DOMAIN = 'UserDomain' GROUP_DOMAIN = 'GroupDomain' class Assignment(assignment.Driver): # Internal interface to manage the database def db_sync(self, version=None): migration.db_sync( sql.get_engine(), migration_helpers.find_migrate_repo(), version=version) def _get_project(self, session, project_id): project_ref = session.query(Project).get(project_id) if project_ref is None: raise exception.ProjectNotFound(project_id=project_id) return project_ref def get_project(self, tenant_id): with sql.transaction() as session: return self._get_project(session, tenant_id).to_dict() def get_project_by_name(self, tenant_name, domain_id): with sql.transaction() as session: query = session.query(Project) query = query.filter_by(name=tenant_name) query = query.filter_by(domain_id=domain_id) try: project_ref = query.one() except sql.NotFound: raise exception.ProjectNotFound(project_id=tenant_name) return project_ref.to_dict() def list_user_ids_for_project(self, tenant_id): with sql.transaction() as session: self._get_project(session, tenant_id) query = session.query(RoleAssignment.actor_id) query = query.filter_by(type=AssignmentType.USER_PROJECT) query = query.filter_by(target_id=tenant_id) assignments = query.all() return [assignment.actor_id for assignment in assignments] def _get_metadata(self, user_id=None, tenant_id=None, domain_id=None, group_id=None, session=None): # TODO(henry-nash): This method represents the last vestiges of the old # metadata concept in this driver. Although we no longer need it here, # since the Manager layer uses the metadata concept across all # assignment drivers, we need to remove it from all of them in order to # finally remove this method. # We aren't given a session when called by the manager directly. if session is None: session = sql.get_session() q = session.query(RoleAssignment) q = q.filter_by(actor_id=user_id or group_id) q = q.filter_by(target_id=tenant_id or domain_id) refs = q.all() if not refs: raise exception.MetadataNotFound() metadata_ref = {} metadata_ref['roles'] = [] for assignment in refs: role_ref = {} role_ref['id'] = assignment.role_id if assignment.inherited and ( assignment.type == AssignmentType.USER_DOMAIN or assignment.type == AssignmentType.GROUP_DOMAIN): role_ref['inherited_to'] = 'projects' metadata_ref['roles'].append(role_ref) return metadata_ref def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): def calculate_type(user_id, group_id, project_id, domain_id): if user_id and project_id: return AssignmentType.USER_PROJECT elif user_id and domain_id: return AssignmentType.USER_DOMAIN elif group_id and project_id: return AssignmentType.GROUP_PROJECT elif group_id and domain_id: return AssignmentType.GROUP_DOMAIN else: message_data = ', '.join( [user_id, group_id, project_id, domain_id]) raise exception.Error(message=_( 'Unexpected combination of grant attributes - ' 'User, Group, Project, Domain: %s') % message_data) with sql.transaction() as session: self._get_role(session, role_id) if domain_id: self._get_domain(session, domain_id) if project_id: self._get_project(session, project_id) if project_id and inherited_to_projects: msg = _('Inherited roles can only be assigned to domains') raise exception.Conflict(type='role grant', details=msg) type = calculate_type(user_id, group_id, project_id, domain_id) try: with sql.transaction() as session: session.add(RoleAssignment( type=type, actor_id=user_id or group_id, target_id=project_id or domain_id, role_id=role_id, inherited=inherited_to_projects)) except sql.DBDuplicateEntry: # The v3 grant APIs are silent if the assignment already exists pass def list_grants(self, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): with sql.transaction() as session: if domain_id: self._get_domain(session, domain_id) if project_id: self._get_project(session, project_id) q = session.query(Role).join(RoleAssignment) q = q.filter(RoleAssignment.actor_id == (user_id or group_id)) q = q.filter(RoleAssignment.target_id == (project_id or domain_id)) q = q.filter(RoleAssignment.inherited == inherited_to_projects) q = q.filter(Role.id == RoleAssignment.role_id) return [x.to_dict() for x in q.all()] def _build_grant_filter(self, session, role_id, user_id, group_id, domain_id, project_id, inherited_to_projects): q = session.query(RoleAssignment) q = q.filter_by(actor_id=user_id or group_id) q = q.filter_by(target_id=project_id or domain_id) q = q.filter_by(role_id=role_id) q = q.filter_by(inherited=inherited_to_projects) return q def get_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): with sql.transaction() as session: role_ref = self._get_role(session, role_id) if domain_id: self._get_domain(session, domain_id) if project_id: self._get_project(session, project_id) try: q = self._build_grant_filter( session, role_id, user_id, group_id, domain_id, project_id, inherited_to_projects) q.one() except sql.NotFound: raise exception.RoleNotFound(role_id=role_id) return role_ref.to_dict() def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): with sql.transaction() as session: self._get_role(session, role_id) if domain_id: self._get_domain(session, domain_id) if project_id: self._get_project(session, project_id) q = self._build_grant_filter( session, role_id, user_id, group_id, domain_id, project_id, inherited_to_projects) if not q.delete(False): raise exception.RoleNotFound(role_id=role_id) @sql.truncated def list_projects(self, hints): with sql.transaction() as session: query = session.query(Project) project_refs = sql.filter_limit_query(Project, query, hints) return [project_ref.to_dict() for project_ref in project_refs] def list_projects_in_domain(self, domain_id): with sql.transaction() as session: self._get_domain(session, domain_id) query = session.query(Project) project_refs = query.filter_by(domain_id=domain_id) return [project_ref.to_dict() for project_ref in project_refs] def list_projects_for_user(self, user_id, group_ids, hints): # TODO(henry-nash): Now that we have a single assignment table, we # should be able to honor the hints list that is provided. def _project_ids_to_dicts(session, ids): if not ids: return [] else: query = session.query(Project) query = query.filter(Project.id.in_(ids)) project_refs = query.all() return [project_ref.to_dict() for project_ref in project_refs] with sql.transaction() as session: # First get a list of the projects and domains for which the user # has any kind of role assigned actor_list = [user_id] if group_ids: actor_list = actor_list + group_ids query = session.query(RoleAssignment) query = query.filter(RoleAssignment.actor_id.in_(actor_list)) assignments = query.all() project_ids = set() for assignment in assignments: if (assignment.type == AssignmentType.USER_PROJECT or assignment.type == AssignmentType.GROUP_PROJECT): project_ids.add(assignment.target_id) if not CONF.os_inherit.enabled: return _project_ids_to_dicts(session, project_ids) # Inherited roles are enabled, so check to see if this user has any # such roles (direct or group) on any domain, in which case we must # add in all the projects in that domain. domain_ids = set() for assignment in assignments: if ((assignment.type == AssignmentType.USER_DOMAIN or assignment.type == AssignmentType.GROUP_DOMAIN) and assignment.inherited): domain_ids.add(assignment.target_id) # Get the projects that are owned by all of these domains and # add them in to the project id list if domain_ids: query = session.query(Project.id) query = query.filter(Project.domain_id.in_(domain_ids)) for project_ref in query.all(): project_ids.add(project_ref.id) return _project_ids_to_dicts(session, project_ids) def get_roles_for_groups(self, group_ids, project_id=None, domain_id=None): if project_id is not None: assignment_type = AssignmentType.GROUP_PROJECT target_id = project_id elif domain_id is not None: assignment_type = AssignmentType.GROUP_DOMAIN target_id = domain_id else: raise AttributeError(_("Must specify either domain or project")) sql_constraints = sqlalchemy.and_( RoleAssignment.type == assignment_type, RoleAssignment.target_id == target_id, Role.id == RoleAssignment.role_id, RoleAssignment.actor_id.in_(group_ids)) session = sql.get_session() with session.begin(): query = session.query(Role).filter( sql_constraints).distinct() return [role.to_dict() for role in query.all()] def _list_entities_for_groups(self, group_ids, entity): if entity == Domain: assignment_type = AssignmentType.GROUP_DOMAIN else: assignment_type = AssignmentType.GROUP_PROJECT group_sql_conditions = sqlalchemy.and_( RoleAssignment.type == assignment_type, entity.id == RoleAssignment.target_id, RoleAssignment.actor_id.in_(group_ids)) session = sql.get_session() with session.begin(): query = session.query(entity).filter( group_sql_conditions) return [x.to_dict() for x in query.all()] def list_projects_for_groups(self, group_ids): return self._list_entities_for_groups(group_ids, Project) def list_domains_for_groups(self, group_ids): return self._list_entities_for_groups(group_ids, Domain) def add_role_to_user_and_project(self, user_id, tenant_id, role_id): with sql.transaction() as session: self._get_project(session, tenant_id) self._get_role(session, role_id) try: with sql.transaction() as session: session.add(RoleAssignment( type=AssignmentType.USER_PROJECT, actor_id=user_id, target_id=tenant_id, role_id=role_id, inherited=False)) except sql.DBDuplicateEntry: msg = ('User %s already has role %s in tenant %s' % (user_id, role_id, tenant_id)) raise exception.Conflict(type='role grant', details=msg) def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=user_id) q = q.filter_by(target_id=tenant_id) q = q.filter_by(role_id=role_id) if q.delete() == 0: raise exception.RoleNotFound(message=_( 'Cannot remove role that has not been granted, %s') % role_id) def list_role_assignments(self): def denormalize_role(ref): assignment = {} if ref.type == AssignmentType.USER_PROJECT: assignment['user_id'] = ref.actor_id assignment['project_id'] = ref.target_id elif ref.type == AssignmentType.USER_DOMAIN: assignment['user_id'] = ref.actor_id assignment['domain_id'] = ref.target_id elif ref.type == AssignmentType.GROUP_PROJECT: assignment['group_id'] = ref.actor_id assignment['project_id'] = ref.target_id elif ref.type == AssignmentType.GROUP_DOMAIN: assignment['group_id'] = ref.actor_id assignment['domain_id'] = ref.target_id else: raise exception.Error(message=_( 'Unexpected assignment type encountered, %s') % ref.type) assignment['role_id'] = ref.role_id if ref.inherited and (ref.type == AssignmentType.USER_DOMAIN or ref.type == AssignmentType.GROUP_DOMAIN): assignment['inherited_to_projects'] = 'projects' return assignment with sql.transaction() as session: refs = session.query(RoleAssignment).all() return [denormalize_role(ref) for ref in refs] # CRUD @sql.handle_conflicts(conflict_type='project') def create_project(self, tenant_id, tenant): tenant['name'] = clean.project_name(tenant['name']) with sql.transaction() as session: tenant_ref = Project.from_dict(tenant) session.add(tenant_ref) return tenant_ref.to_dict() @sql.handle_conflicts(conflict_type='project') def update_project(self, tenant_id, tenant): if 'name' in tenant: tenant['name'] = clean.project_name(tenant['name']) with sql.transaction() as session: tenant_ref = self._get_project(session, tenant_id) old_project_dict = tenant_ref.to_dict() for k in tenant: old_project_dict[k] = tenant[k] new_project = Project.from_dict(old_project_dict) for attr in Project.attributes: if attr != 'id': setattr(tenant_ref, attr, getattr(new_project, attr)) tenant_ref.extra = new_project.extra return tenant_ref.to_dict(include_extra_dict=True) @sql.handle_conflicts(conflict_type='project') def delete_project(self, tenant_id): with sql.transaction() as session: tenant_ref = self._get_project(session, tenant_id) q = session.query(RoleAssignment) q = q.filter_by(target_id=tenant_id) q.delete(False) session.delete(tenant_ref) # domain crud @sql.handle_conflicts(conflict_type='domain') def create_domain(self, domain_id, domain): with sql.transaction() as session: ref = Domain.from_dict(domain) session.add(ref) return ref.to_dict() @sql.truncated def list_domains(self, hints): with sql.transaction() as session: query = session.query(Domain) refs = sql.filter_limit_query(Domain, query, hints) return [ref.to_dict() for ref in refs] def _get_domain(self, session, domain_id): ref = session.query(Domain).get(domain_id) if ref is None: raise exception.DomainNotFound(domain_id=domain_id) return ref def get_domain(self, domain_id): with sql.transaction() as session: return self._get_domain(session, domain_id).to_dict() def get_domain_by_name(self, domain_name): with sql.transaction() as session: try: ref = (session.query(Domain). filter_by(name=domain_name).one()) except sql.NotFound: raise exception.DomainNotFound(domain_id=domain_name) return ref.to_dict() @sql.handle_conflicts(conflict_type='domain') def update_domain(self, domain_id, domain): with sql.transaction() as session: ref = self._get_domain(session, domain_id) old_dict = ref.to_dict() for k in domain: old_dict[k] = domain[k] new_domain = Domain.from_dict(old_dict) for attr in Domain.attributes: if attr != 'id': setattr(ref, attr, getattr(new_domain, attr)) ref.extra = new_domain.extra return ref.to_dict() def delete_domain(self, domain_id): with sql.transaction() as session: ref = self._get_domain(session, domain_id) # TODO(henry-nash): Although the controller will ensure deletion of # all users & groups within the domain (which will cause all # assignments for those users/groups to also be deleted), there # could still be assignments on this domain for users/groups in # other domains - so we should delete these here (see Bug #1277847) session.delete(ref) # role crud @sql.handle_conflicts(conflict_type='role') def create_role(self, role_id, role): with sql.transaction() as session: ref = Role.from_dict(role) session.add(ref) return ref.to_dict() @sql.truncated def list_roles(self, hints): with sql.transaction() as session: query = session.query(Role) refs = sql.filter_limit_query(Role, query, hints) return [ref.to_dict() for ref in refs] def _get_role(self, session, role_id): ref = session.query(Role).get(role_id) if ref is None: raise exception.RoleNotFound(role_id=role_id) return ref def get_role(self, role_id): with sql.transaction() as session: return self._get_role(session, role_id).to_dict() @sql.handle_conflicts(conflict_type='role') def update_role(self, role_id, role): with sql.transaction() as session: ref = self._get_role(session, role_id) old_dict = ref.to_dict() for k in role: old_dict[k] = role[k] new_role = Role.from_dict(old_dict) for attr in Role.attributes: if attr != 'id': setattr(ref, attr, getattr(new_role, attr)) ref.extra = new_role.extra return ref.to_dict() def delete_role(self, role_id): with sql.transaction() as session: ref = self._get_role(session, role_id) q = session.query(RoleAssignment) q = q.filter_by(role_id=role_id) q.delete(False) session.delete(ref) def delete_user(self, user_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=user_id) q.delete(False) def delete_group(self, group_id): with sql.transaction() as session: q = session.query(RoleAssignment) q = q.filter_by(actor_id=group_id) q.delete(False) class Domain(sql.ModelBase, sql.DictBase): __tablename__ = 'domain' attributes = ['id', 'name', 'enabled'] id = sql.Column(sql.String(64), primary_key=True) name = sql.Column(sql.String(64), nullable=False) enabled = sql.Column(sql.Boolean, default=True, nullable=False) extra = sql.Column(sql.JsonBlob()) __table_args__ = (sql.UniqueConstraint('name'), {}) class Project(sql.ModelBase, sql.DictBase): __tablename__ = 'project' attributes = ['id', 'name', 'domain_id', 'description', 'enabled'] id = sql.Column(sql.String(64), primary_key=True) name = sql.Column(sql.String(64), nullable=False) domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'), nullable=False) description = sql.Column(sql.Text()) enabled = sql.Column(sql.Boolean) extra = sql.Column(sql.JsonBlob()) # Unique constraint across two columns to create the separation # rather than just only 'name' being unique __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {}) class Role(sql.ModelBase, sql.DictBase): __tablename__ = 'role' attributes = ['id', 'name'] id = sql.Column(sql.String(64), primary_key=True) name = sql.Column(sql.String(255), nullable=False) extra = sql.Column(sql.JsonBlob()) __table_args__ = (sql.UniqueConstraint('name'), {}) class RoleAssignment(sql.ModelBase, sql.DictBase): __tablename__ = 'assignment' attributes = ['type', 'actor_id', 'target_id', 'role_id', 'inherited'] # NOTE(henry-nash); Postgres requires a name to be defined for an Enum type = sql.Column( sql.Enum(AssignmentType.USER_PROJECT, AssignmentType.GROUP_PROJECT, AssignmentType.USER_DOMAIN, AssignmentType.GROUP_DOMAIN, name='type'), nullable=False) actor_id = sql.Column(sql.String(64), nullable=False) target_id = sql.Column(sql.String(64), nullable=False) role_id = sql.Column(sql.String(64), sql.ForeignKey('role.id'), nullable=False) inherited = sql.Column(sql.Boolean, default=False, nullable=False) __table_args__ = (sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id'), {}) def to_dict(self): """Override parent to_dict() method with a simpler implementation. RoleAssignment doesn't have non-indexed 'extra' attributes, so the parent implementation is not applicable. """ return dict(six.iteritems(self)) keystone-2014.1/keystone/assignment/backends/ldap.py0000664000175400017540000007015112323716272023666 0ustar jenkinsjenkins00000000000000# Copyright 2012-2013 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. from __future__ import absolute_import import uuid import ldap as ldap from keystone import assignment from keystone import clean from keystone.common import driver_hints from keystone.common import ldap as common_ldap from keystone.common import models from keystone import config from keystone import exception from keystone.identity.backends import ldap as ldap_identity from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) class Assignment(assignment.Driver): def __init__(self): super(Assignment, self).__init__() self.LDAP_URL = CONF.ldap.url self.LDAP_USER = CONF.ldap.user self.LDAP_PASSWORD = CONF.ldap.password self.suffix = CONF.ldap.suffix #These are the only deep dependency from assignment back #to identity. The assumption is that if you are using #LDAP for assignments, you are using it for Id as well. self.user = ldap_identity.UserApi(CONF) self.group = ldap_identity.GroupApi(CONF) self.project = ProjectApi(CONF) self.role = RoleApi(CONF) def get_project(self, tenant_id): return self._set_default_domain(self.project.get(tenant_id)) def list_projects(self, hints): return self._set_default_domain(self.project.get_all()) def list_projects_in_domain(self, domain_id): # We don't support multiple domains within this driver, so ignore # any domain specified return self.list_projects(driver_hints.Hints()) def get_project_by_name(self, tenant_name, domain_id): self._validate_default_domain_id(domain_id) return self._set_default_domain(self.project.get_by_name(tenant_name)) def create_project(self, tenant_id, tenant): self.project.check_allow_create() tenant = self._validate_default_domain(tenant) tenant['name'] = clean.project_name(tenant['name']) data = tenant.copy() if 'id' not in data or data['id'] is None: data['id'] = str(uuid.uuid4().hex) if 'description' in data and data['description'] in ['', None]: data.pop('description') return self._set_default_domain(self.project.create(data)) def update_project(self, tenant_id, tenant): self.project.check_allow_update() tenant = self._validate_default_domain(tenant) if 'name' in tenant: tenant['name'] = clean.project_name(tenant['name']) return self._set_default_domain(self.project.update(tenant_id, tenant)) def _get_metadata(self, user_id=None, tenant_id=None, domain_id=None, group_id=None): def _get_roles_for_just_user_and_project(user_id, tenant_id): self.get_project(tenant_id) return [self.role._dn_to_id(a.role_dn) for a in self.role.get_role_assignments (self.project._id_to_dn(tenant_id)) if self.user._dn_to_id(a.user_dn) == user_id] def _get_roles_for_group_and_project(group_id, project_id): self.get_project(project_id) group_dn = self.group._id_to_dn(group_id) # NOTE(marcos-fermin-lobo): In Active Directory, for functions # such as "self.role.get_role_assignments", it returns # the key "CN" or "OU" in uppercase. # The group_dn var has "CN" and "OU" in lowercase. # For this reason, it is necessary to use the "upper()" # function so both are consistent. return [self.role._dn_to_id(a.role_dn) for a in self.role.get_role_assignments (self.project._id_to_dn(project_id)) if a.user_dn.upper() == group_dn.upper()] if domain_id is not None: msg = _('Domain metadata not supported by LDAP') raise exception.NotImplemented(message=msg) if group_id is None and user_id is None: return {} if tenant_id is None: return {} if user_id is None: metadata_ref = _get_roles_for_group_and_project(group_id, tenant_id) else: metadata_ref = _get_roles_for_just_user_and_project(user_id, tenant_id) if not metadata_ref: return {} return {'roles': [self._role_to_dict(r, False) for r in metadata_ref]} def get_role(self, role_id): return self.role.get(role_id) def list_roles(self, hints): return self.role.get_all() def list_projects_for_user(self, user_id, group_ids, hints): # NOTE(henry-nash): The LDAP backend is being deprecated, so no # support is provided for projects that the user has a role on solely # by virtue of group membership. user_dn = self.user._id_to_dn(user_id) associations = (self.role.list_project_roles_for_user (user_dn, self.project.tree_dn)) # Since the LDAP backend doesn't store the domain_id in the LDAP # records (and only supports the default domain), we fill in the # domain_id before we return the list. return [self._set_default_domain(x) for x in self.project.get_user_projects(user_dn, associations)] def get_roles_for_groups(self, group_ids, project_id=None, domain_id=None): raise exception.NotImplemented() def list_projects_for_groups(self, group_ids): raise exception.NotImplemented() def list_domains_for_groups(self, group_ids): raise exception.NotImplemented() def list_user_ids_for_project(self, tenant_id): self.get_project(tenant_id) tenant_dn = self.project._id_to_dn(tenant_id) rolegrants = self.role.get_role_assignments(tenant_dn) return [self.user._dn_to_id(user_dn) for user_dn in self.project.get_user_dns(tenant_id, rolegrants)] def _subrole_id_to_dn(self, role_id, tenant_id): if tenant_id is None: return self.role._id_to_dn(role_id) else: return '%s=%s,%s' % (self.role.id_attr, ldap.dn.escape_dn_chars(role_id), self.project._id_to_dn(tenant_id)) def add_role_to_user_and_project(self, user_id, tenant_id, role_id): self.get_project(tenant_id) self.get_role(role_id) user_dn = self.user._id_to_dn(user_id) role_dn = self._subrole_id_to_dn(role_id, tenant_id) self.role.add_user(role_id, role_dn, user_dn, user_id, tenant_id) tenant_dn = self.project._id_to_dn(tenant_id) return UserRoleAssociation(role_dn=role_dn, user_dn=user_dn, tenant_dn=tenant_dn) def _add_role_to_group_and_project(self, group_id, tenant_id, role_id): self.get_project(tenant_id) self.get_role(role_id) group_dn = self.group._id_to_dn(group_id) role_dn = self._subrole_id_to_dn(role_id, tenant_id) self.role.add_user(role_id, role_dn, group_dn, group_id, tenant_id) tenant_dn = self.project._id_to_dn(tenant_id) return GroupRoleAssociation(group_dn=group_dn, role_dn=role_dn, tenant_dn=tenant_dn) def create_role(self, role_id, role): self.role.check_allow_create() try: self.get_role(role_id) except exception.NotFound: pass else: msg = _('Duplicate ID, %s.') % role_id raise exception.Conflict(type='role', details=msg) try: self.role.get_by_name(role['name']) except exception.NotFound: pass else: msg = _('Duplicate name, %s.') % role['name'] raise exception.Conflict(type='role', details=msg) return self.role.create(role) def delete_role(self, role_id): self.role.check_allow_delete() return self.role.delete(role_id, self.project.tree_dn) def delete_project(self, tenant_id): self.project.check_allow_delete() if self.project.subtree_delete_enabled: self.project.deleteTree(tenant_id) else: tenant_dn = self.project._id_to_dn(tenant_id) self.role.roles_delete_subtree_by_project(tenant_dn) self.project.delete(tenant_id) def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): role_dn = self._subrole_id_to_dn(role_id, tenant_id) return self.role.delete_user(role_dn, self.user._id_to_dn(user_id), self.project._id_to_dn(tenant_id), user_id, role_id) def _remove_role_from_group_and_project(self, group_id, tenant_id, role_id): role_dn = self._subrole_id_to_dn(role_id, tenant_id) return self.role.delete_user(role_dn, self.group._id_to_dn(group_id), self.project._id_to_dn(tenant_id), group_id, role_id) def update_role(self, role_id, role): self.role.check_allow_update() self.get_role(role_id) return self.role.update(role_id, role) def create_domain(self, domain_id, domain): if domain_id == CONF.identity.default_domain_id: msg = _('Duplicate ID, %s.') % domain_id raise exception.Conflict(type='domain', details=msg) raise exception.Forbidden(_('Domains are read-only against LDAP')) def get_domain(self, domain_id): self._validate_default_domain_id(domain_id) return assignment.calc_default_domain() def update_domain(self, domain_id, domain): self._validate_default_domain_id(domain_id) raise exception.Forbidden(_('Domains are read-only against LDAP')) def delete_domain(self, domain_id): self._validate_default_domain_id(domain_id) raise exception.Forbidden(_('Domains are read-only against LDAP')) def list_domains(self, hints): return [assignment.calc_default_domain()] #Bulk actions on User From identity def delete_user(self, user_id): user_dn = self.user._id_to_dn(user_id) for ref in self.role.list_global_roles_for_user(user_dn): self.role.delete_user(ref.role_dn, ref.user_dn, ref.project_dn, user_id, self.role._dn_to_id(ref.role_dn)) for ref in self.role.list_project_roles_for_user(user_dn, self.project.tree_dn): self.role.delete_user(ref.role_dn, ref.user_dn, ref.project_dn, user_id, self.role._dn_to_id(ref.role_dn)) user = self.user.get(user_id) if hasattr(user, 'tenant_id'): self.project.remove_user(user.tenant_id, self.user._id_to_dn(user_id)) #LDAP assignments only supports LDAP identity. Assignments under identity #are already deleted def delete_group(self, group_id): if not self.group.subtree_delete_enabled: # TODO(spzala): this is only placeholder for group and domain # role support which will be added under bug 1101287 query = '(objectClass=%s)' % self.group.object_class dn = None dn = self.group._id_to_dn(group_id) if dn: try: conn = self.group.get_connection() roles = conn.search_s(dn, ldap.SCOPE_ONELEVEL, query, ['%s' % '1.1']) for role_dn, i in roles: conn.delete_s(role_dn) except ldap.NO_SUCH_OBJECT: pass finally: conn.unbind_s() def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): self.get_role(role_id) if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) if project_id and inherited_to_projects: msg = _('Inherited roles can only be assigned to domains') raise exception.Conflict(type='role grant', details=msg) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} if user_id is None: metadata_ref['roles'] = self._add_role_to_group_and_project( group_id, project_id, role_id) else: metadata_ref['roles'] = self.add_role_to_user_and_project( user_id, project_id, role_id) def get_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): role_ref = self.get_role(role_id) if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} role_ids = set(self._roles_from_role_dicts( metadata_ref.get('roles', []), inherited_to_projects)) if role_id not in role_ids: raise exception.RoleNotFound(role_id=role_id) return role_ref def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): self.get_role(role_id) if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} try: if user_id is None: metadata_ref['roles'] = ( self._remove_role_from_group_and_project( group_id, project_id, role_id)) else: metadata_ref['roles'] = self.remove_role_from_user_and_project( user_id, project_id, role_id) except KeyError: raise exception.RoleNotFound(role_id=role_id) def list_grants(self, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} return [self.get_role(x) for x in self._roles_from_role_dicts(metadata_ref.get('roles', []), inherited_to_projects)] def get_domain_by_name(self, domain_name): default_domain = assignment.calc_default_domain() if domain_name != default_domain['name']: raise exception.DomainNotFound(domain_id=domain_name) return default_domain def list_role_assignments(self): role_assignments = [] for a in self.role.list_role_assignments(self.project.tree_dn): assignment = {'role_id': self.role._dn_to_id(a.role_dn), 'user_id': self.user._dn_to_id(a.user_dn), 'project_id': self.project._dn_to_id(a.project_dn)} role_assignments.append(assignment) return role_assignments # TODO(termie): turn this into a data object and move logic to driver class ProjectApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap): DEFAULT_OU = 'ou=Groups' DEFAULT_STRUCTURAL_CLASSES = [] DEFAULT_OBJECTCLASS = 'groupOfNames' DEFAULT_ID_ATTR = 'cn' DEFAULT_MEMBER_ATTRIBUTE = 'member' NotFound = exception.ProjectNotFound notfound_arg = 'project_id' # NOTE(yorik-sar): while options_name = tenant options_name = 'tenant' attribute_options_names = {'name': 'name', 'description': 'desc', 'enabled': 'enabled', 'domain_id': 'domain_id'} immutable_attrs = ['name'] model = models.Project def __init__(self, conf): super(ProjectApi, self).__init__(conf) self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute') or self.DEFAULT_MEMBER_ATTRIBUTE) def create(self, values): data = values.copy() if data.get('id') is None: data['id'] = uuid.uuid4().hex return super(ProjectApi, self).create(data) def get_user_projects(self, user_dn, associations): """Returns list of tenants a user has access to """ project_ids = set() for assoc in associations: project_ids.add(self._dn_to_id(assoc.project_dn)) projects = [] for project_id in project_ids: #slower to get them one at a time, but a huge list could blow out #the connection. This is the safer way projects.append(self.get(project_id)) return projects def add_user(self, tenant_id, user_dn): conn = self.get_connection() try: conn.modify_s( self._id_to_dn(tenant_id), [(ldap.MOD_ADD, self.member_attribute, user_dn)]) except ldap.TYPE_OR_VALUE_EXISTS: # As adding a user to a tenant is done implicitly in several # places, and is not part of the exposed API, it's easier for us to # just ignore this instead of raising exception.Conflict. pass finally: conn.unbind_s() def remove_user(self, tenant_id, user_dn, user_id): conn = self.get_connection() try: conn.modify_s(self._id_to_dn(tenant_id), [(ldap.MOD_DELETE, self.member_attribute, user_dn)]) except ldap.NO_SUCH_ATTRIBUTE: raise exception.NotFound(user_id) finally: conn.unbind_s() def get_user_dns(self, tenant_id, rolegrants, role_dn=None): tenant = self._ldap_get(tenant_id) res = set() if not role_dn: # Get users who have default tenant mapping for user_dn in tenant[1].get(self.member_attribute, []): if self.use_dumb_member and user_dn == self.dumb_member: continue res.add(user_dn) # Get users who are explicitly mapped via a tenant for rolegrant in rolegrants: if role_dn is None or rolegrant.role_dn == role_dn: res.add(rolegrant.user_dn) return list(res) def update(self, project_id, values): old_obj = self.get(project_id) return super(ProjectApi, self).update(project_id, values, old_obj) class UserRoleAssociation(object): """Role Grant model.""" def __init__(self, user_dn=None, role_dn=None, tenant_dn=None, *args, **kw): self.user_dn = user_dn self.role_dn = role_dn self.project_dn = tenant_dn class GroupRoleAssociation(object): """Role Grant model.""" def __init__(self, group_dn=None, role_dn=None, tenant_dn=None, *args, **kw): self.group_dn = group_dn self.role_dn = role_dn self.project_dn = tenant_dn # TODO(termie): turn this into a data object and move logic to driver class RoleApi(common_ldap.BaseLdap): DEFAULT_OU = 'ou=Roles' DEFAULT_STRUCTURAL_CLASSES = [] DEFAULT_OBJECTCLASS = 'organizationalRole' DEFAULT_MEMBER_ATTRIBUTE = 'roleOccupant' NotFound = exception.RoleNotFound options_name = 'role' attribute_options_names = {'name': 'name'} immutable_attrs = ['id'] model = models.Role def __init__(self, conf): super(RoleApi, self).__init__(conf) self.member_attribute = (getattr(conf.ldap, 'role_member_attribute') or self.DEFAULT_MEMBER_ATTRIBUTE) def get(self, role_id, role_filter=None): model = super(RoleApi, self).get(role_id, role_filter) return model def create(self, values): return super(RoleApi, self).create(values) def add_user(self, role_id, role_dn, user_dn, user_id, tenant_id=None): conn = self.get_connection() try: conn.modify_s(role_dn, [(ldap.MOD_ADD, self.member_attribute, user_dn)]) except ldap.TYPE_OR_VALUE_EXISTS: msg = (_('User %(user_id)s already has role %(role_id)s in ' 'tenant %(tenant_id)s') % dict(user_id=user_id, role_id=role_id, tenant_id=tenant_id)) raise exception.Conflict(type='role grant', details=msg) except ldap.NO_SUCH_OBJECT: if tenant_id is None or self.get(role_id) is None: raise Exception(_("Role %s not found") % (role_id,)) attrs = [('objectClass', [self.object_class]), (self.member_attribute, [user_dn])] if self.use_dumb_member: attrs[1][1].append(self.dumb_member) try: conn.add_s(role_dn, attrs) except Exception as inst: raise inst finally: conn.unbind_s() def delete_user(self, role_dn, user_dn, tenant_dn, user_id, role_id): conn = self.get_connection() try: conn.modify_s(role_dn, [(ldap.MOD_DELETE, self.member_attribute, user_dn)]) except (ldap.NO_SUCH_OBJECT, ldap.NO_SUCH_ATTRIBUTE): raise exception.RoleNotFound(message=_( 'Cannot remove role that has not been granted, %s') % role_id) finally: conn.unbind_s() def get_role_assignments(self, tenant_dn): conn = self.get_connection() query = '(objectClass=%s)' % self.object_class try: roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query) except ldap.NO_SUCH_OBJECT: return [] finally: conn.unbind_s() res = [] for role_dn, attrs in roles: try: user_dns = attrs[self.member_attribute] except KeyError: continue for user_dn in user_dns: if self.use_dumb_member and user_dn == self.dumb_member: continue res.append(UserRoleAssociation( user_dn=user_dn, role_dn=role_dn, tenant_dn=tenant_dn)) return res def list_global_roles_for_user(self, user_dn): roles = self.get_all('(%s=%s)' % (self.member_attribute, user_dn)) return [UserRoleAssociation( role_dn=role.dn, user_dn=user_dn) for role in roles] def list_project_roles_for_user(self, user_dn, project_subtree): conn = self.get_connection() query = '(&(objectClass=%s)(%s=%s))' % (self.object_class, self.member_attribute, user_dn) try: roles = conn.search_s(project_subtree, ldap.SCOPE_SUBTREE, query) except ldap.NO_SUCH_OBJECT: return [] finally: conn.unbind_s() res = [] for role_dn, _ in roles: #ldap.dn.dn2str returns an array, where the first #element is the first segment. #For a role assignment, this contains the role ID, #The remainder is the DN of the tenant. tenant = ldap.dn.str2dn(role_dn) tenant.pop(0) tenant_dn = ldap.dn.dn2str(tenant) res.append(UserRoleAssociation( user_dn=user_dn, role_dn=role_dn, tenant_dn=tenant_dn)) return res def roles_delete_subtree_by_project(self, tenant_dn): conn = self.get_connection() query = '(objectClass=%s)' % self.object_class try: roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query) for role_dn, _ in roles: try: conn.delete_s(role_dn) except Exception as inst: raise inst except ldap.NO_SUCH_OBJECT: pass finally: conn.unbind_s() def update(self, role_id, role): try: old_name = self.get_by_name(role['name']) raise exception.Conflict(_('Cannot duplicate name %s') % old_name) except exception.NotFound: pass return super(RoleApi, self).update(role_id, role) def delete(self, role_id, tenant_dn): conn = self.get_connection() query = '(&(objectClass=%s)(%s=%s))' % (self.object_class, self.id_attr, role_id) try: for role_dn, _ in conn.search_s(tenant_dn, ldap.SCOPE_SUBTREE, query): conn.delete_s(role_dn) except ldap.NO_SUCH_OBJECT: pass finally: conn.unbind_s() super(RoleApi, self).delete(role_id) def list_role_assignments(self, project_tree_dn): """Returns a list of all the role assignments linked to project_tree_dn attribute. """ conn = self.get_connection() query = '(objectClass=%s)' % (self.object_class) try: roles = conn.search_s(project_tree_dn, ldap.SCOPE_SUBTREE, query) except ldap.NO_SUCH_OBJECT: return [] finally: conn.unbind_s() res = [] for role_dn, role in roles: tenant = ldap.dn.str2dn(role_dn) tenant.pop(0) # It obtains the tenant DN to construct the UserRoleAssociation # object. tenant_dn = ldap.dn.dn2str(tenant) for user_dn in role[self.member_attribute]: # NOTE(nkinder): Ideally, this comparison would be aware of the # Distinguished Name LDAP syntax. Since Keystone is responsible # for setting the dumb member DN, we are relatively sure that # it is returned in the same form. We still need to do a case # insensitive comparison since attribute names will be upper # case for AD. We already do this elsewhere in the LDAP # driver, so it's OK until we decide to become syntax aware. if (self.use_dumb_member and user_dn.lower() == self.dumb_member.lower()): continue res.append(UserRoleAssociation( user_dn=user_dn, role_dn=role_dn, tenant_dn=tenant_dn)) return res keystone-2014.1/keystone/assignment/backends/kvs.py0000664000175400017540000005077712323716272023565 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone import assignment from keystone import clean from keystone.common import kvs from keystone import exception from keystone.openstack.common.gettextutils import _ class Assignment(kvs.Base, assignment.Driver): """KVS Assignment backend. This backend uses the following mappings to store data: * Domains: * domain_list -> [domain_id, ...] * domain-{id} -> domain_ref * domain_name-{name} -> domain_ref * Projects: * tenant-{id} -> project_ref * tenant_name-{name} -> project_ref * Roles: * role_list -> [role_id, ...] * role-{id} -> role_ref * Role assignments: * metadata_user-{target}-{user_id} -> {'roles': [{'id': role-id, ...}, ...]} * metadata_group-{target}-{group_id} -> {'roles': [{'id': role-id, ...}, ...]} """ # Public interface def get_project(self, tenant_id): try: return self.db.get('tenant-%s' % tenant_id) except exception.NotFound: raise exception.ProjectNotFound(project_id=tenant_id) def _build_project_refs(self): project_keys = (k for k in self.db.keys() if k.startswith('tenant-')) return [self.db.get(key) for key in project_keys] def list_projects(self, hints): return self._build_project_refs() def list_projects_in_domain(self, domain_id): project_refs = self._build_project_refs() self.get_domain(domain_id) return [ref for ref in project_refs if domain_id in ref['domain_id']] def get_project_by_name(self, tenant_name, domain_id): try: return self.db.get('tenant_name-%s' % tenant_name) except exception.NotFound: raise exception.ProjectNotFound(project_id=tenant_name) def list_user_ids_for_project(self, tenant_id): self.get_project(tenant_id) user_ids = set() metadata_keys = (k for k in self.db.keys() if k.startswith('metadata_user-')) for key in metadata_keys: i, meta_project_or_domain_id, meta_user_id = key.split('-') if meta_project_or_domain_id != tenant_id: # target is not the project, so on to next metadata. continue user_ids.add(meta_user_id) return list(user_ids) def _get_metadata(self, user_id=None, tenant_id=None, domain_id=None, group_id=None): try: if user_id: if tenant_id: return self.db.get('metadata_user-%s-%s' % (tenant_id, user_id)) else: return self.db.get('metadata_user-%s-%s' % (domain_id, user_id)) else: if tenant_id: return self.db.get('metadata_group-%s-%s' % (tenant_id, group_id)) else: return self.db.get('metadata_group-%s-%s' % (domain_id, group_id)) except exception.NotFound: raise exception.MetadataNotFound() def get_role(self, role_id): try: return self.db.get('role-%s' % role_id) except exception.NotFound: raise exception.RoleNotFound(role_id=role_id) def list_roles(self, hints): return self._list_roles() def _list_roles(self): role_ids = self.db.get('role_list', []) return [self.get_role(x) for x in role_ids] def list_projects_for_user(self, user_id, group_ids, hints): # NOTE(henry-nash): The kvs backend is being deprecated, so no # support is provided for projects that the user has a role on solely # by virtue of group membership. project_ids = set() metadata_keys = (k for k in self.db.keys() if k.startswith('metadata_user-')) for key in metadata_keys: i, meta_project_or_domain_id, meta_user_id = key.split('-') if meta_user_id != user_id: # Not the user, so on to next metadata. continue try: self.get_project(meta_project_or_domain_id) except exception.NotFound: # target is not a project, so on to next metadata. continue project_id = meta_project_or_domain_id project_ids.add(project_id) project_refs = [] for project_id in project_ids: project_refs.append(self.get_project(project_id)) return project_refs def get_roles_for_groups(self, group_ids, project_id=None, domain_id=None): raise exception.NotImplemented() def list_projects_for_groups(self, group_ids): raise exception.NotImplemented() def list_domains_for_groups(self, group_ids): raise exception.NotImplemented() def add_role_to_user_and_project(self, user_id, tenant_id, role_id): self.get_project(tenant_id) self.get_role(role_id) try: metadata_ref = self._get_metadata(user_id, tenant_id) except exception.MetadataNotFound: metadata_ref = {} try: metadata_ref['roles'] = self._add_role_to_role_dicts( role_id, False, metadata_ref.get('roles', []), allow_existing=False) except KeyError: msg = ('User %s already has role %s in tenant %s' % (user_id, role_id, tenant_id)) raise exception.Conflict(type='role grant', details=msg) self._update_metadata(user_id, tenant_id, metadata_ref) def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): try: metadata_ref = self._get_metadata(user_id, tenant_id) except exception.MetadataNotFound: metadata_ref = {} try: metadata_ref['roles'] = self._remove_role_from_role_dicts( role_id, False, metadata_ref.get('roles', [])) except KeyError: raise exception.RoleNotFound(message=_( 'Cannot remove role that has not been granted, %s') % role_id) if metadata_ref['roles']: self._update_metadata(user_id, tenant_id, metadata_ref) else: self.db.delete('metadata_user-%s-%s' % (tenant_id, user_id)) def list_role_assignments(self): """List the role assignments. We enumerate the metadata entries and extract the targets, actors, and roles. """ assignment_list = [] metadata_keys = (k for k in self.db.keys() if k.startswith('metadata_user-')) for key in metadata_keys: template = {} i, meta_project_or_domain_id, template['user_id'] = key.split('-') try: self.get_project(meta_project_or_domain_id) template['project_id'] = meta_project_or_domain_id except exception.NotFound: template['domain_id'] = meta_project_or_domain_id entry = self.db.get(key) inherited = False for r in self._roles_from_role_dicts(entry.get('roles', {}), inherited): role_assignment = template.copy() role_assignment['role_id'] = r assignment_list.append(role_assignment) metadata_keys = (k for k in self.db.keys() if k.startswith('metadata_group-')) for key in metadata_keys: template = {} i, meta_project_or_domain_id, template['group_id'] = key.split('-') try: self.get_project(meta_project_or_domain_id) template['project_id'] = meta_project_or_domain_id except exception.NotFound: template['domain_id'] = meta_project_or_domain_id entry = self.db.get(key) inherited = False for r in self._roles_from_role_dicts(entry.get('roles', {}), inherited): role_assignment = template.copy() role_assignment['role_id'] = r assignment_list.append(role_assignment) return assignment_list # CRUD def create_project(self, tenant_id, tenant): tenant['name'] = clean.project_name(tenant['name']) try: self.get_project(tenant_id) except exception.ProjectNotFound: pass else: msg = 'Duplicate ID, %s.' % tenant_id raise exception.Conflict(type='tenant', details=msg) try: self.get_project_by_name(tenant['name'], tenant['domain_id']) except exception.ProjectNotFound: pass else: msg = 'Duplicate name, %s.' % tenant['name'] raise exception.Conflict(type='tenant', details=msg) self.db.set('tenant-%s' % tenant_id, tenant) self.db.set('tenant_name-%s' % tenant['name'], tenant) return tenant def update_project(self, tenant_id, tenant): if 'name' in tenant: tenant['name'] = clean.project_name(tenant['name']) try: existing = self.db.get('tenant_name-%s' % tenant['name']) if existing and tenant_id != existing['id']: msg = 'Duplicate name, %s.' % tenant['name'] raise exception.Conflict(type='tenant', details=msg) except exception.NotFound: pass # get the old name and delete it too try: old_project = self.db.get('tenant-%s' % tenant_id) except exception.NotFound: raise exception.ProjectNotFound(project_id=tenant_id) new_project = old_project.copy() new_project.update(tenant) new_project['id'] = tenant_id self.db.delete('tenant_name-%s' % old_project['name']) self.db.set('tenant-%s' % tenant_id, new_project) self.db.set('tenant_name-%s' % new_project['name'], new_project) return new_project def delete_project(self, tenant_id): try: old_project = self.db.get('tenant-%s' % tenant_id) except exception.NotFound: raise exception.ProjectNotFound(project_id=tenant_id) self.db.delete('tenant_name-%s' % old_project['name']) self.db.delete('tenant-%s' % tenant_id) def _create_metadata(self, user_id, tenant_id, metadata, domain_id=None, group_id=None): return self._update_metadata(user_id, tenant_id, metadata, domain_id, group_id) def _update_metadata(self, user_id, tenant_id, metadata, domain_id=None, group_id=None): if user_id: if tenant_id: self.db.set('metadata_user-%s-%s' % (tenant_id, user_id), metadata) else: self.db.set('metadata_user-%s-%s' % (domain_id, user_id), metadata) else: if tenant_id: self.db.set('metadata_group-%s-%s' % (tenant_id, group_id), metadata) else: self.db.set('metadata_group-%s-%s' % (domain_id, group_id), metadata) return metadata def create_role(self, role_id, role): try: self.get_role(role_id) except exception.RoleNotFound: pass else: msg = 'Duplicate ID, %s.' % role_id raise exception.Conflict(type='role', details=msg) for role_ref in self._list_roles(): if role['name'] == role_ref['name']: msg = 'Duplicate name, %s.' % role['name'] raise exception.Conflict(type='role', details=msg) self.db.set('role-%s' % role_id, role) role_list = set(self.db.get('role_list', [])) role_list.add(role_id) self.db.set('role_list', list(role_list)) return role def update_role(self, role_id, role): old_role_ref = None for role_ref in self._list_roles(): if role['name'] == role_ref['name'] and role_id != role_ref['id']: msg = 'Duplicate name, %s.' % role['name'] raise exception.Conflict(type='role', details=msg) if role_id == role_ref['id']: old_role_ref = role_ref if old_role_ref is None: raise exception.RoleNotFound(role_id=role_id) new_role = old_role_ref.copy() new_role.update(role) new_role['id'] = role_id self.db.set('role-%s' % role_id, new_role) return role def delete_role(self, role_id): self.get_role(role_id) metadata_keys = (k for k in self.db.keys() if k.startswith('metadata_user-')) for key in metadata_keys: i, meta_project_or_domain_id, meta_user_id = key.split('-') try: self.delete_grant(role_id, project_id=meta_project_or_domain_id, user_id=meta_user_id) except exception.NotFound: pass try: self.delete_grant(role_id, domain_id=meta_project_or_domain_id, user_id=meta_user_id) except exception.NotFound: pass metadata_keys = (k for k in self.db.keys() if k.startswith('metadata_group-')) for key in metadata_keys: i, meta_project_or_domain_id, meta_group_id = key.split('-') try: self.delete_grant(role_id, project_id=meta_project_or_domain_id, group_id=meta_group_id) except exception.NotFound: pass try: self.delete_grant(role_id, domain_id=meta_project_or_domain_id, group_id=meta_group_id) except exception.NotFound: pass self.db.delete('role-%s' % role_id) role_list = set(self.db.get('role_list', [])) role_list.remove(role_id) self.db.set('role_list', list(role_list)) def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): self.get_role(role_id) if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} metadata_ref['roles'] = self._add_role_to_role_dicts( role_id, inherited_to_projects, metadata_ref.get('roles', [])) self._update_metadata(user_id, project_id, metadata_ref, domain_id, group_id) def list_grants(self, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} return [self.get_role(x) for x in self._roles_from_role_dicts(metadata_ref.get('roles', []), inherited_to_projects)] def get_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): self.get_role(role_id) if group_id: self.get_group(group_id) if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} role_ids = set(self._roles_from_role_dicts( metadata_ref.get('roles', []), inherited_to_projects)) if role_id not in role_ids: raise exception.RoleNotFound(role_id=role_id) return self.get_role(role_id) def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): self.get_role(role_id) if domain_id: self.get_domain(domain_id) if project_id: self.get_project(project_id) try: metadata_ref = self._get_metadata(user_id, project_id, domain_id, group_id) except exception.MetadataNotFound: metadata_ref = {} try: metadata_ref['roles'] = self._remove_role_from_role_dicts( role_id, inherited_to_projects, metadata_ref.get('roles', [])) except KeyError: raise exception.RoleNotFound(role_id=role_id) self._update_metadata(user_id, project_id, metadata_ref, domain_id, group_id) # domain crud def create_domain(self, domain_id, domain): try: self.get_domain(domain_id) except exception.DomainNotFound: pass else: msg = 'Duplicate ID, %s.' % domain_id raise exception.Conflict(type='domain', details=msg) try: self.get_domain_by_name(domain['name']) except exception.DomainNotFound: pass else: msg = 'Duplicate name, %s.' % domain['name'] raise exception.Conflict(type='domain', details=msg) self.db.set('domain-%s' % domain_id, domain) self.db.set('domain_name-%s' % domain['name'], domain) domain_list = set(self.db.get('domain_list', [])) domain_list.add(domain_id) self.db.set('domain_list', list(domain_list)) return domain def list_domains(self, hints): domain_ids = self.db.get('domain_list', []) return [self.get_domain(x) for x in domain_ids] def get_domain(self, domain_id): try: return self.db.get('domain-%s' % domain_id) except exception.NotFound: raise exception.DomainNotFound(domain_id=domain_id) def get_domain_by_name(self, domain_name): try: return self.db.get('domain_name-%s' % domain_name) except exception.NotFound: raise exception.DomainNotFound(domain_id=domain_name) def update_domain(self, domain_id, domain): orig_domain = self.get_domain(domain_id) domain['id'] = domain_id self.db.set('domain-%s' % domain_id, domain) self.db.set('domain_name-%s' % domain['name'], domain) if domain['name'] != orig_domain['name']: self.db.delete('domain_name-%s' % orig_domain['name']) return domain def delete_domain(self, domain_id): domain = self.get_domain(domain_id) self.db.delete('domain-%s' % domain_id) self.db.delete('domain_name-%s' % domain['name']) domain_list = set(self.db.get('domain_list', [])) domain_list.remove(domain_id) self.db.set('domain_list', list(domain_list)) def delete_user(self, user_id): """Deletes all assignments for a user. :raises: keystone.exception.RoleNotFound """ raise exception.NotImplemented() def delete_group(self, group_id): """Deletes all assignments for a group. :raises: keystone.exception.RoleNotFound """ raise exception.NotImplemented() keystone-2014.1/keystone/assignment/backends/__init__.py0000664000175400017540000000000012323716267024473 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/assignment/__init__.py0000664000175400017540000000132512323716272022730 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2013 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. from keystone.assignment import controllers from keystone.assignment.core import * from keystone.assignment import routers keystone-2014.1/keystone/routers.py0000664000175400017540000000522012323716267020526 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """ The only types of routers in this file should be ``ComposingRouters``. The routers for the backends should be in the backend-specific router modules. For example, the ``ComposableRouter`` for ``identity`` belongs in:: keystone.identity.routers """ from keystone.common import wsgi from keystone import controllers class Extension(wsgi.ComposableRouter): def __init__(self, is_admin=True): if is_admin: self.controller = controllers.AdminExtensions() else: self.controller = controllers.PublicExtensions() def add_routes(self, mapper): extensions_controller = self.controller mapper.connect('/extensions', controller=extensions_controller, action='get_extensions_info', conditions=dict(method=['GET'])) mapper.connect('/extensions/{extension_alias}', controller=extensions_controller, action='get_extension_info', conditions=dict(method=['GET'])) class VersionV2(wsgi.ComposableRouter): def __init__(self, description): self.description = description def add_routes(self, mapper): version_controller = controllers.Version(self.description) mapper.connect('/', controller=version_controller, action='get_version_v2') class VersionV3(wsgi.ComposableRouter): def __init__(self, description): self.description = description def add_routes(self, mapper): version_controller = controllers.Version(self.description) mapper.connect('/', controller=version_controller, action='get_version_v3') class Versions(wsgi.ComposableRouter): def __init__(self, description): self.description = description def add_routes(self, mapper): version_controller = controllers.Version(self.description) mapper.connect('/', controller=version_controller, action='get_versions') keystone-2014.1/keystone/identity/0000775000175400017540000000000012323716511020273 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/identity/controllers.py0000664000175400017540000004403612323716272023226 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Workflow Logic the Identity service.""" import functools import inspect import six import uuid from keystone.assignment import controllers as assignment_controllers from keystone.common import controller from keystone.common import dependency from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log from keystone.openstack.common import versionutils CONF = config.CONF LOG = log.getLogger(__name__) class DeprecatedMeta(type): """Metaclass that ensures that the correct methods on the deprecated classes are reported as deprecated on call. """ @staticmethod def moved_to_assignment(class_name): # NOTE(morganfainberg): wrapper for versionutils.deprecated decorator # with some values populated specifically for the migration for # controllers from identity to assignment. def inner(f): subst = {'cls_name': class_name, 'meth_name': f.__name__} what = 'identity.controllers.%(cls_name)s.%(meth_name)s' % subst favor = 'assignment.controllers.%(cls_name)s.%(meth_name)s' % subst deprecated = versionutils.deprecated( versionutils.deprecated.ICEHOUSE, what=what, in_favor_of=favor, remove_in=+1) return deprecated(f) return inner @staticmethod def _is_wrappable(item): # NOTE(morganfainberg): Wrapping non-callables, non-methods, and # builtins is not the point of the deprecation warnings. Simple test # to ensure the item is one of the types that should be wrapped. if (callable(item) and inspect.ismethod(item) and not inspect.isbuiltin(item)): return True return False def __new__(mcs, class_name, bases, namespace): def get_attribute(self, item): # NOTE(morganfainberg): This implementation of __getattribute__ # is automatically added to any classes using the DeprecatedMeta # metaclass. This will apply the moved_to_assignment wrapper to # method calls (inherited or direct). attr = super(bases[0], self).__getattribute__(item) if DeprecatedMeta._is_wrappable(attr): return DeprecatedMeta.moved_to_assignment(class_name)(attr) return attr namespace['__getattribute__'] = get_attribute return type.__new__(mcs, class_name, bases, namespace) def __getattribute__(cls, item): # NOTE(morganfainberg): This implementation of __getattribute__ catches # non-instantiated calls to @classmethods. attr = type.__getattribute__(cls, item) if DeprecatedMeta._is_wrappable(attr): if (issubclass(cls, controller.V3Controller) and DeprecatedMeta._is_wrappable(attr)): attr = DeprecatedMeta.moved_to_assignment(cls.__name__)(attr) return attr @dependency.requires('assignment_api', 'identity_api') class User(controller.V2Controller): @controller.v2_deprecated def get_user(self, context, user_id): self.assert_admin(context) ref = self.identity_api.get_user(user_id) return {'user': self.v3_to_v2_user(ref)} @controller.v2_deprecated def get_users(self, context): # NOTE(termie): i can't imagine that this really wants all the data # about every single user in the system... if 'name' in context['query_string']: return self.get_user_by_name( context, context['query_string'].get('name')) self.assert_admin(context) user_list = self.identity_api.list_users() return {'users': self.v3_to_v2_user(user_list)} @controller.v2_deprecated def get_user_by_name(self, context, user_name): self.assert_admin(context) ref = self.identity_api.get_user_by_name( user_name, CONF.identity.default_domain_id) return {'user': self.v3_to_v2_user(ref)} # CRUD extension @controller.v2_deprecated def create_user(self, context, user): user = self._normalize_OSKSADM_password_on_request(user) user = self.normalize_username_in_request(user) user = self._normalize_dict(user) self.assert_admin(context) if 'name' not in user or not user['name']: msg = _('Name field is required and cannot be empty') raise exception.ValidationError(message=msg) if 'enabled' in user and not isinstance(user['enabled'], bool): msg = _('Enabled field must be a boolean') raise exception.ValidationError(message=msg) default_project_id = user.pop('tenantId', None) if default_project_id is not None: # Check to see if the project is valid before moving on. self.assignment_api.get_project(default_project_id) user['default_project_id'] = default_project_id user_id = uuid.uuid4().hex user_ref = self._normalize_domain_id(context, user.copy()) user_ref['id'] = user_id new_user_ref = self.v3_to_v2_user( self.identity_api.create_user(user_id, user_ref)) if default_project_id is not None: self.assignment_api.add_user_to_project(default_project_id, user_id) return {'user': new_user_ref} @controller.v2_deprecated def update_user(self, context, user_id, user): # NOTE(termie): this is really more of a patch than a put user = self.normalize_username_in_request(user) self.assert_admin(context) if 'enabled' in user and not isinstance(user['enabled'], bool): msg = _('Enabled field should be a boolean') raise exception.ValidationError(message=msg) default_project_id = user.pop('tenantId', None) if default_project_id is not None: user['default_project_id'] = default_project_id old_user_ref = self.v3_to_v2_user( self.identity_api.get_user(user_id)) # Check whether a tenant is being added or changed for the user. # Catch the case where the tenant is being changed for a user and also # where a user previously had no tenant but a tenant is now being # added for the user. if (('tenantId' in old_user_ref and old_user_ref['tenantId'] != default_project_id and default_project_id is not None) or ('tenantId' not in old_user_ref and default_project_id is not None)): # Make sure the new project actually exists before we perform the # user update. self.assignment_api.get_project(default_project_id) user_ref = self.v3_to_v2_user( self.identity_api.update_user(user_id, user)) # If 'tenantId' is in either ref, we might need to add or remove the # user from a project. if 'tenantId' in user_ref or 'tenantId' in old_user_ref: if user_ref['tenantId'] != old_user_ref.get('tenantId'): if old_user_ref.get('tenantId'): try: member_role_id = config.CONF.member_role_id self.assignment_api.remove_role_from_user_and_project( user_id, old_user_ref['tenantId'], member_role_id) except exception.NotFound: # NOTE(morganfainberg): This is not a critical error it # just means that the user cannot be removed from the # old tenant. This could occur if roles aren't found # or if the project is invalid or if there are no roles # for the user on that project. msg = _('Unable to remove user %(user)s from ' '%(tenant)s.') LOG.warning(msg, {'user': user_id, 'tenant': old_user_ref['tenantId']}) if user_ref['tenantId']: try: self.assignment_api.add_user_to_project( user_ref['tenantId'], user_id) except exception.Conflict: # We are already a member of that tenant pass except exception.NotFound: # NOTE(morganfainberg): Log this and move on. This is # not the end of the world if we can't add the user to # the appropriate tenant. Most of the time this means # that the project is invalid or roles are some how # incorrect. This shouldn't prevent the return of the # new ref. msg = _('Unable to add user %(user)s to %(tenant)s.') LOG.warning(msg, {'user': user_id, 'tenant': user_ref['tenantId']}) return {'user': user_ref} @controller.v2_deprecated def delete_user(self, context, user_id): self.assert_admin(context) self.identity_api.delete_user(user_id) @controller.v2_deprecated def set_user_enabled(self, context, user_id, user): return self.update_user(context, user_id, user) @controller.v2_deprecated def set_user_password(self, context, user_id, user): user = self._normalize_OSKSADM_password_on_request(user) return self.update_user(context, user_id, user) @staticmethod def _normalize_OSKSADM_password_on_request(ref): """Sets the password from the OS-KSADM Admin Extension. The OS-KSADM Admin Extension documentation says that `OS-KSADM:password` can be used in place of `password`. """ if 'OS-KSADM:password' in ref: ref['password'] = ref.pop('OS-KSADM:password') return ref @dependency.requires('identity_api') class UserV3(controller.V3Controller): collection_name = 'users' member_name = 'user' def __init__(self): super(UserV3, self).__init__() self.get_member_from_driver = self.identity_api.get_user def _check_user_and_group_protection(self, context, prep_info, user_id, group_id): ref = {} ref['user'] = self.identity_api.get_user(user_id) ref['group'] = self.identity_api.get_group(group_id) self.check_protection(context, prep_info, ref) @controller.protected() def create_user(self, context, user): self._require_attribute(user, 'name') ref = self._assign_unique_id(self._normalize_dict(user)) ref = self._normalize_domain_id(context, ref) ref = self.identity_api.create_user(ref['id'], ref) return UserV3.wrap_member(context, ref) @controller.filterprotected('domain_id', 'email', 'enabled', 'name') def list_users(self, context, filters): hints = UserV3.build_driver_hints(context, filters) refs = self.identity_api.list_users( domain_scope=self._get_domain_id_for_request(context), hints=hints) return UserV3.wrap_collection(context, refs, hints=hints) @controller.filterprotected('domain_id', 'email', 'enabled', 'name') def list_users_in_group(self, context, filters, group_id): hints = UserV3.build_driver_hints(context, filters) refs = self.identity_api.list_users_in_group( group_id, domain_scope=self._get_domain_id_for_request(context), hints=hints) return UserV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_user(self, context, user_id): ref = self.identity_api.get_user( user_id, domain_scope=self._get_domain_id_for_request(context)) return UserV3.wrap_member(context, ref) def _update_user(self, context, user_id, user, domain_scope): self._require_matching_id(user_id, user) self._require_matching_domain_id( user_id, user, functools.partial(self.identity_api.get_user, domain_scope=domain_scope)) ref = self.identity_api.update_user( user_id, user, domain_scope=domain_scope) return UserV3.wrap_member(context, ref) @controller.protected() def update_user(self, context, user_id, user): domain_scope = self._get_domain_id_for_request(context) return self._update_user(context, user_id, user, domain_scope) @controller.protected(callback=_check_user_and_group_protection) def add_user_to_group(self, context, user_id, group_id): self.identity_api.add_user_to_group( user_id, group_id, domain_scope=self._get_domain_id_for_request(context)) @controller.protected(callback=_check_user_and_group_protection) def check_user_in_group(self, context, user_id, group_id): self.identity_api.check_user_in_group( user_id, group_id, domain_scope=self._get_domain_id_for_request(context)) @controller.protected(callback=_check_user_and_group_protection) def remove_user_from_group(self, context, user_id, group_id): self.identity_api.remove_user_from_group( user_id, group_id, domain_scope=self._get_domain_id_for_request(context)) @controller.protected() def delete_user(self, context, user_id): # Make sure any tokens are marked as deleted domain_id = self._get_domain_id_for_request(context) # Finally delete the user itself - the backend is # responsible for deleting any role assignments related # to this user return self.identity_api.delete_user(user_id, domain_scope=domain_id) @controller.protected() def change_password(self, context, user_id, user): original_password = user.get('original_password') if original_password is None: raise exception.ValidationError(target='user', attribute='original_password') password = user.get('password') if password is None: raise exception.ValidationError(target='user', attribute='password') domain_scope = self._get_domain_id_for_request(context) try: self.identity_api.change_password( context, user_id, original_password, password, domain_scope) except AssertionError: raise exception.Unauthorized() @dependency.requires('identity_api') class GroupV3(controller.V3Controller): collection_name = 'groups' member_name = 'group' def __init__(self): super(GroupV3, self).__init__() self.get_member_from_driver = self.identity_api.get_group @controller.protected() def create_group(self, context, group): self._require_attribute(group, 'name') ref = self._assign_unique_id(self._normalize_dict(group)) ref = self._normalize_domain_id(context, ref) ref = self.identity_api.create_group(ref['id'], ref) return GroupV3.wrap_member(context, ref) @controller.filterprotected('domain_id', 'name') def list_groups(self, context, filters): hints = GroupV3.build_driver_hints(context, filters) refs = self.identity_api.list_groups( domain_scope=self._get_domain_id_for_request(context), hints=hints) return GroupV3.wrap_collection(context, refs, hints=hints) @controller.filterprotected('name') def list_groups_for_user(self, context, filters, user_id): hints = GroupV3.build_driver_hints(context, filters) refs = self.identity_api.list_groups_for_user( user_id, domain_scope=self._get_domain_id_for_request(context), hints=hints) return GroupV3.wrap_collection(context, refs, hints=hints) @controller.protected() def get_group(self, context, group_id): ref = self.identity_api.get_group( group_id, domain_scope=self._get_domain_id_for_request(context)) return GroupV3.wrap_member(context, ref) @controller.protected() def update_group(self, context, group_id, group): self._require_matching_id(group_id, group) domain_scope = self._get_domain_id_for_request(context) self._require_matching_domain_id( group_id, group, functools.partial(self.identity_api.get_group, domain_scope=domain_scope)) ref = self.identity_api.update_group( group_id, group, domain_scope=domain_scope) return GroupV3.wrap_member(context, ref) @controller.protected() def delete_group(self, context, group_id): domain_id = self._get_domain_id_for_request(context) self.identity_api.delete_group(group_id, domain_scope=domain_id) # TODO(morganfainberg): Remove proxy compat classes once Icehouse is released. @six.add_metaclass(DeprecatedMeta) class Tenant(assignment_controllers.Tenant): pass @six.add_metaclass(DeprecatedMeta) class Role(assignment_controllers.Role): pass @six.add_metaclass(DeprecatedMeta) class DomainV3(assignment_controllers.DomainV3): pass @six.add_metaclass(DeprecatedMeta) class ProjectV3(assignment_controllers.ProjectV3): pass @six.add_metaclass(DeprecatedMeta) class RoleV3(assignment_controllers.RoleV3): pass @six.add_metaclass(DeprecatedMeta) class RoleAssignmentV3(assignment_controllers.RoleAssignmentV3): pass keystone-2014.1/keystone/identity/core.py0000664000175400017540000007114112323716272021605 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """Main entry point into the Identity service.""" import abc import functools import os from oslo.config import cfg import six from keystone import clean from keystone.common import dependency from keystone.common import driver_hints from keystone.common import manager from keystone import config from keystone import exception from keystone import notifications from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone.openstack.common import log from keystone.openstack.common import versionutils CONF = config.CONF LOG = log.getLogger(__name__) def moved_to_assignment(f): name = f.__name__ deprecated = versionutils.deprecated(versionutils.deprecated.ICEHOUSE, what="identity_api." + name, in_favor_of="assignment_api." + name, remove_in=+1) return deprecated(f) def filter_user(user_ref): """Filter out private items in a user dict. 'password', 'tenants' and 'groups' are never returned. :returns: user_ref """ if user_ref: user_ref = user_ref.copy() user_ref.pop('password', None) user_ref.pop('tenants', None) user_ref.pop('groups', None) user_ref.pop('domains', None) try: user_ref['extra'].pop('password', None) user_ref['extra'].pop('tenants', None) except KeyError: pass return user_ref class DomainConfigs(dict): """Discover, store and provide access to domain specific configs. The setup_domain_drivers() call will be made via the wrapper from the first call to any driver function handled by this manager. This setup call it will scan the domain config directory for files of the form keystone..conf For each file, the domain_name will be turned into a domain_id and then this class will: - Create a new config structure, adding in the specific additional options defined in this config file - Initialise a new instance of the required driver with this new config. """ configured = False driver = None def _load_driver(self, assignment_api, domain_id): domain_config = self[domain_id] domain_config['driver'] = ( importutils.import_object( domain_config['cfg'].identity.driver, domain_config['cfg'])) domain_config['driver'].assignment_api = assignment_api def _load_config(self, assignment_api, file_list, domain_name): try: domain_ref = assignment_api.get_domain_by_name(domain_name) except exception.DomainNotFound: LOG.warning( _('Invalid domain name (%s) found in config file name'), domain_name) return # Create a new entry in the domain config dict, which contains # a new instance of both the conf environment and driver using # options defined in this set of config files. Later, when we # service calls via this Manager, we'll index via this domain # config dict to make sure we call the right driver domain = domain_ref['id'] self[domain] = {} self[domain]['cfg'] = cfg.ConfigOpts() config.configure(conf=self[domain]['cfg']) self[domain]['cfg'](args=[], project='keystone', default_config_files=file_list) self._load_driver(assignment_api, domain) def setup_domain_drivers(self, standard_driver, assignment_api): # This is called by the api call wrapper self.configured = True self.driver = standard_driver conf_dir = CONF.identity.domain_config_dir if not os.path.exists(conf_dir): LOG.warning(_('Unable to locate domain config directory: %s'), conf_dir) return for r, d, f in os.walk(conf_dir): for fname in f: if fname.startswith('keystone.') and fname.endswith('.conf'): names = fname.split('.') if len(names) == 3: self._load_config(assignment_api, [os.path.join(r, fname)], names[1]) else: LOG.debug(_('Ignoring file (%s) while scanning domain ' 'config directory'), fname) def get_domain_driver(self, domain_id): if domain_id in self: return self[domain_id]['driver'] def get_domain_conf(self, domain_id): if domain_id in self: return self[domain_id]['cfg'] def reload_domain_driver(self, assignment_api, domain_id): # Only used to support unit tests that want to set # new config values. This should only be called once # the domains have been configured, since it relies on # the fact that the configuration files have already been # read. if self.configured: if domain_id in self: self._load_driver(assignment_api, domain_id) else: # The standard driver self.driver = self.driver() self.driver.assignment_api = assignment_api def domains_configured(f): """Wraps API calls to lazy load domain configs after init. This is required since the assignment manager needs to be initialized before this manager, and yet this manager's init wants to be able to make assignment calls (to build the domain configs). So instead, we check if the domains have been initialized on entry to each call, and if requires load them, """ @functools.wraps(f) def wrapper(self, *args, **kwargs): if (not self.domain_configs.configured and CONF.identity.domain_specific_drivers_enabled): LOG.warning(_( 'Running an experimental and unsupported configuration ' '(domain_specific_drivers_enabled = True); ' 'this will result in known issues.')) self.domain_configs.setup_domain_drivers( self.driver, self.assignment_api) return f(self, *args, **kwargs) return wrapper @dependency.provider('identity_api') @dependency.optional('revoke_api') @dependency.requires('assignment_api', 'credential_api', 'token_api') class Manager(manager.Manager): """Default pivot point for the Identity backend. See :mod:`keystone.common.manager.Manager` for more details on how this dynamically calls the backend. This class also handles the support of domain specific backends, by using the DomainConfigs class. The setup call for DomainConfigs is called from with the @domains_configured wrapper in a lazy loading fashion to get around the fact that we can't satisfy the assignment api it needs from within our __init__() function since the assignment driver is not itself yet initialized. Each of the identity calls are pre-processed here to choose, based on domain, which of the drivers should be called. The non-domain-specific driver is still in place, and is used if there is no specific driver for the domain in question. """ _USER = 'user' _GROUP = 'group' def __init__(self): super(Manager, self).__init__(CONF.identity.driver) self.domain_configs = DomainConfigs() # Domain ID normalization methods def _set_domain_id(self, ref, domain_id): if isinstance(ref, dict): ref = ref.copy() ref['domain_id'] = domain_id return ref elif isinstance(ref, list): return [self._set_domain_id(x, domain_id) for x in ref] else: raise ValueError(_('Expected dict or list: %s') % type(ref)) def _clear_domain_id(self, ref): # Clear the domain_id, and then check to ensure that if this # was not the default domain, it is being handled by its own # backend driver. ref = ref.copy() domain_id = ref.pop('domain_id', CONF.identity.default_domain_id) if (domain_id != CONF.identity.default_domain_id and domain_id not in self.domain_configs): raise exception.DomainNotFound(domain_id=domain_id) return ref def _normalize_scope(self, domain_scope): if domain_scope is None: return CONF.identity.default_domain_id else: return domain_scope def _select_identity_driver(self, domain_id): driver = self.domain_configs.get_domain_driver(domain_id) if driver: return driver else: self.assignment_api.get_domain(domain_id) return self.driver def _get_domain_id_and_driver(self, domain_scope): domain_id = self._normalize_scope(domain_scope) driver = self._select_identity_driver(domain_id) return (domain_id, driver) def _mark_domain_id_filter_satisfied(self, hints): if hints: for filter in hints.filters(): if (filter['name'] == 'domain_id' and filter['comparator'] == 'equals'): hints.remove(filter) # The actual driver calls - these are pre/post processed here as # part of the Manager layer to make sure we: # # - select the right driver for this domain # - clear/set domain_ids for drivers that do not support domains @notifications.emit_event('authenticate') @domains_configured def authenticate(self, context, user_id, password, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) ref = driver.authenticate(user_id, password) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @notifications.created(_USER) @domains_configured def create_user(self, user_id, user_ref): user = user_ref.copy() user['name'] = clean.user_name(user['name']) user.setdefault('enabled', True) user['enabled'] = clean.user_enabled(user['enabled']) # For creating a user, the domain is in the object itself domain_id = user_ref['domain_id'] driver = self._select_identity_driver(domain_id) if not driver.is_domain_aware(): user = self._clear_domain_id(user) ref = driver.create_user(user_id, user) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @domains_configured def get_user(self, user_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) ref = driver.get_user(user_id) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @domains_configured def get_user_by_name(self, user_name, domain_id): driver = self._select_identity_driver(domain_id) ref = driver.get_user_by_name(user_name, domain_id) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @manager.response_truncated @domains_configured def list_users(self, domain_scope=None, hints=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) if not driver.is_domain_aware(): # We are effectively satisfying any domain_id filter by the above # driver selection, so remove any such filter self._mark_domain_id_filter_satisfied(hints) ref_list = driver.list_users(hints or driver_hints.Hints()) if not driver.is_domain_aware(): ref_list = self._set_domain_id(ref_list, domain_id) return ref_list @notifications.updated(_USER) @domains_configured def update_user(self, user_id, user_ref, domain_scope=None): user = user_ref.copy() if 'name' in user: user['name'] = clean.user_name(user['name']) if 'enabled' in user: user['enabled'] = clean.user_enabled(user['enabled']) domain_id, driver = self._get_domain_id_and_driver(domain_scope) if not driver.is_domain_aware(): user = self._clear_domain_id(user) ref = driver.update_user(user_id, user) if user.get('enabled') is False or user.get('password') is not None: if self.revoke_api: self.revoke_api.revoke_by_user(user_id) self.token_api.delete_tokens_for_user(user_id) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @notifications.deleted(_USER) @domains_configured def delete_user(self, user_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) driver.delete_user(user_id) self.credential_api.delete_credentials_for_user(user_id) self.token_api.delete_tokens_for_user(user_id) @notifications.created(_GROUP) @domains_configured def create_group(self, group_id, group_ref): group = group_ref.copy() group.setdefault('description', '') # For creating a group, the domain is in the object itself domain_id = group_ref['domain_id'] driver = self._select_identity_driver(domain_id) if not driver.is_domain_aware(): group = self._clear_domain_id(group) ref = driver.create_group(group_id, group) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @domains_configured def get_group(self, group_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) ref = driver.get_group(group_id) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref @notifications.updated(_GROUP) @domains_configured def update_group(self, group_id, group, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) if not driver.is_domain_aware(): group = self._clear_domain_id(group) ref = driver.update_group(group_id, group) if not driver.is_domain_aware(): ref = self._set_domain_id(ref, domain_id) return ref def revoke_tokens_for_group(self, group_id, domain_scope): # We get the list of users before we attempt the group # deletion, so that we can remove these tokens after we know # the group deletion succeeded. # TODO(ayoung): revoke based on group and roleids instead user_ids = [] for u in self.list_users_in_group(group_id, domain_scope): user_ids.append(u['id']) if self.revoke_api: self.revoke_api.revoke_by_user(u['id']) self.token_api.delete_tokens_for_users(user_ids) @notifications.deleted(_GROUP) @domains_configured def delete_group(self, group_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) # As well as deleting the group, we need to invalidate # any tokens for the users who are members of the group. self.revoke_tokens_for_group(group_id, domain_scope) driver.delete_group(group_id) @domains_configured def add_user_to_group(self, user_id, group_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) driver.add_user_to_group(user_id, group_id) self.token_api.delete_tokens_for_user(user_id) @domains_configured def remove_user_from_group(self, user_id, group_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) driver.remove_user_from_group(user_id, group_id) # TODO(ayoung) revoking all tokens for a user based on group # membership is overkill, as we only would need to revoke tokens # that had role assignments via the group. Calculating those # assignments would have to be done by the assignment backend. if self.revoke_api: self.revoke_api.revoke_by_user(user_id) self.token_api.delete_tokens_for_user(user_id) @manager.response_truncated @domains_configured def list_groups_for_user(self, user_id, domain_scope=None, hints=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) if not driver.is_domain_aware(): # We are effectively satisfying any domain_id filter by the above # driver selection, so remove any such filter self._mark_domain_id_filter_satisfied(hints) ref_list = driver.list_groups_for_user( user_id, hints or driver_hints.Hints()) if not driver.is_domain_aware(): ref_list = self._set_domain_id(ref_list, domain_id) return ref_list @manager.response_truncated @domains_configured def list_groups(self, domain_scope=None, hints=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) if not driver.is_domain_aware(): # We are effectively satisfying any domain_id filter by the above # driver selection, so remove any such filter self._mark_domain_id_filter_satisfied(hints) ref_list = driver.list_groups(hints or driver_hints.Hints()) if not driver.is_domain_aware(): ref_list = self._set_domain_id(ref_list, domain_id) return ref_list @manager.response_truncated @domains_configured def list_users_in_group(self, group_id, domain_scope=None, hints=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) if not driver.is_domain_aware(): # We are effectively satisfying any domain_id filter by the above # driver selection, so remove any such filter self._mark_domain_id_filter_satisfied(hints) ref_list = driver.list_users_in_group( group_id, hints or driver_hints.Hints()) if not driver.is_domain_aware(): ref_list = self._set_domain_id(ref_list, domain_id) return ref_list @domains_configured def check_user_in_group(self, user_id, group_id, domain_scope=None): domain_id, driver = self._get_domain_id_and_driver(domain_scope) driver.check_user_in_group(user_id, group_id) @domains_configured def change_password(self, context, user_id, original_password, new_password, domain_scope): # authenticate() will raise an AssertionError if authentication fails self.authenticate(context, user_id, original_password, domain_scope=domain_scope) update_dict = {'password': new_password} self.update_user(user_id, update_dict, domain_scope=domain_scope) # TODO(morganfainberg): Remove the following deprecated methods once # Icehouse is released. Maintain identity -> assignment proxy for 1 # release. @moved_to_assignment def get_domain_by_name(self, domain_name): return self.assignment_api.get_domain_by_name(domain_name) @moved_to_assignment def get_domain(self, domain_id): return self.assignment_api.get_domain(domain_id) @moved_to_assignment def update_domain(self, domain_id, domain): return self.assignment_api.update_domain(domain_id, domain) @moved_to_assignment def list_domains(self, hints=None): return self.assignment_api.list_domains(hints=hints) @moved_to_assignment def delete_domain(self, domain_id): return self.assignment_api.delete_domain(domain_id) @moved_to_assignment def create_domain(self, domain_id, domain): return self.assignment_api.create_domain(domain_id, domain) @moved_to_assignment def list_projects_for_user(self, user_id): return self.assignment_api.list_projects_for_user(user_id) @moved_to_assignment def add_user_to_project(self, tenant_id, user_id): return self.assignment_api.add_user_to_project(tenant_id, user_id) @moved_to_assignment def remove_user_from_project(self, tenant_id, user_id): return self.assignment_api.remove_user_from_project(tenant_id, user_id) @moved_to_assignment def get_project(self, tenant_id): return self.assignment_api.get_project(tenant_id) @moved_to_assignment def list_projects(self, hints=None): return self.assignment_api.list_projects(hints=hints) @moved_to_assignment def get_role(self, role_id): return self.assignment_api.get_role(role_id) @moved_to_assignment def list_roles(self, hints=None): return self.assignment_api.list_roles(hints=hints) @moved_to_assignment def get_project_users(self, tenant_id): return self.assignment_api.get_project_users(tenant_id) @moved_to_assignment def get_roles_for_user_and_project(self, user_id, tenant_id): return self.assignment_api.get_roles_for_user_and_project( user_id, tenant_id) @moved_to_assignment def get_roles_for_user_and_domain(self, user_id, domain_id): return (self.assignment_api.get_roles_for_user_and_domain (user_id, domain_id)) @moved_to_assignment def add_role_to_user_and_project(self, user_id, tenant_id, role_id): return (self.assignment_api.add_role_to_user_and_project (user_id, tenant_id, role_id)) @moved_to_assignment def create_role(self, role_id, role): return self.assignment_api.create_role(role_id, role) @moved_to_assignment def delete_role(self, role_id): return self.assignment_api.delete_role(role_id) @moved_to_assignment def remove_role_from_user_and_project(self, user_id, tenant_id, role_id): return (self.assignment_api.remove_role_from_user_and_project (user_id, tenant_id, role_id)) @moved_to_assignment def update_role(self, role_id, role): return self.assignment_api.update_role(role_id, role) @moved_to_assignment def create_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): return (self.assignment_api.create_grant (role_id, user_id, group_id, domain_id, project_id, inherited_to_projects)) @moved_to_assignment def list_grants(self, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): return (self.assignment_api.list_grants (user_id, group_id, domain_id, project_id, inherited_to_projects)) @moved_to_assignment def get_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): return (self.assignment_api.get_grant (role_id, user_id, group_id, domain_id, project_id, inherited_to_projects)) @moved_to_assignment def delete_grant(self, role_id, user_id=None, group_id=None, domain_id=None, project_id=None, inherited_to_projects=False): return (self.assignment_api.delete_grant (role_id, user_id, group_id, domain_id, project_id, inherited_to_projects)) @six.add_metaclass(abc.ABCMeta) class Driver(object): """Interface description for an Identity driver.""" def _get_list_limit(self): return CONF.identity.list_limit or CONF.list_limit @abc.abstractmethod def authenticate(self, user_id, password): """Authenticate a given user and password. :returns: user_ref :raises: AssertionError """ raise exception.NotImplemented() # user crud @abc.abstractmethod def create_user(self, user_id, user): """Creates a new user. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_users(self, hints): """List users in the system. :param hints: filter hints which the driver should implement if at all possible. :returns: a list of user_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def list_users_in_group(self, group_id, hints): """List users in a group. :param group_id: the group in question :param hints: filter hints which the driver should implement if at all possible. :returns: a list of user_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_user(self, user_id): """Get a user by ID. :returns: user_ref :raises: keystone.exception.UserNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_user(self, user_id, user): """Updates an existing user. :raises: keystone.exception.UserNotFound, keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def add_user_to_group(self, user_id, group_id): """Adds a user to a group. :raises: keystone.exception.UserNotFound, keystone.exception.GroupNotFound """ raise exception.NotImplemented() @abc.abstractmethod def check_user_in_group(self, user_id, group_id): """Checks if a user is a member of a group. :raises: keystone.exception.UserNotFound, keystone.exception.GroupNotFound """ raise exception.NotImplemented() @abc.abstractmethod def remove_user_from_group(self, user_id, group_id): """Removes a user from a group. :raises: keystone.exception.NotFound """ raise exception.NotImplemented() @abc.abstractmethod def delete_user(self, user_id): """Deletes an existing user. :raises: keystone.exception.UserNotFound """ raise exception.NotImplemented() @abc.abstractmethod def get_user_by_name(self, user_name, domain_id): """Get a user by name. :returns: user_ref :raises: keystone.exception.UserNotFound """ raise exception.NotImplemented() # group crud @abc.abstractmethod def create_group(self, group_id, group): """Creates a new group. :raises: keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def list_groups(self, hints): """List groups in the system. :param hints: filter hints which the driver should implement if at all possible. :returns: a list of group_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def list_groups_for_user(self, user_id, hints): """List groups a user is in :param user_id: the user in question :param hints: filter hints which the driver should implement if at all possible. :returns: a list of group_refs or an empty list. """ raise exception.NotImplemented() @abc.abstractmethod def get_group(self, group_id): """Get a group by ID. :returns: group_ref :raises: keystone.exception.GroupNotFound """ raise exception.NotImplemented() @abc.abstractmethod def update_group(self, group_id, group): """Updates an existing group. :raises: keystone.exceptionGroupNotFound, keystone.exception.Conflict """ raise exception.NotImplemented() @abc.abstractmethod def delete_group(self, group_id): """Deletes an existing group. :raises: keystone.exception.GroupNotFound """ raise exception.NotImplemented() @abc.abstractmethod def is_domain_aware(self): """Indicates if Driver supports domains.""" raise exception.NotImplemented() #end of identity keystone-2014.1/keystone/identity/routers.py0000664000175400017540000000506712323716267022370 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. """WSGI Routers for the Identity service.""" from keystone.common import router from keystone.common import wsgi from keystone.identity import controllers class Admin(wsgi.ComposableRouter): def add_routes(self, mapper): # User Operations user_controller = controllers.User() mapper.connect('/users/{user_id}', controller=user_controller, action='get_user', conditions=dict(method=['GET'])) def append_v3_routers(mapper, routers): user_controller = controllers.UserV3() routers.append( router.Router(user_controller, 'users', 'user')) mapper.connect('/users/{user_id}/password', controller=user_controller, action='change_password', conditions=dict(method=['POST'])) mapper.connect('/groups/{group_id}/users', controller=user_controller, action='list_users_in_group', conditions=dict(method=['GET'])) mapper.connect('/groups/{group_id}/users/{user_id}', controller=user_controller, action='add_user_to_group', conditions=dict(method=['PUT'])) mapper.connect('/groups/{group_id}/users/{user_id}', controller=user_controller, action='check_user_in_group', conditions=dict(method=['HEAD'])) mapper.connect('/groups/{group_id}/users/{user_id}', controller=user_controller, action='remove_user_from_group', conditions=dict(method=['DELETE'])) group_controller = controllers.GroupV3() routers.append( router.Router(group_controller, 'groups', 'group')) mapper.connect('/users/{user_id}/groups', controller=group_controller, action='list_groups_for_user', conditions=dict(method=['GET'])) keystone-2014.1/keystone/identity/backends/0000775000175400017540000000000012323716511022045 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/identity/backends/sql.py0000664000175400017540000002732312323716272023231 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import dependency from keystone.common import sql from keystone.common.sql import migration_helpers from keystone.common import utils from keystone import exception from keystone import identity from keystone.openstack.common.db.sqlalchemy import migration from keystone.openstack.common.gettextutils import _ # Import assignment sql to ensure that the models defined in there are # available for the reference from User and Group to Domain.id. from keystone.assignment.backends import sql as assignment_sql # flake8: noqa class User(sql.ModelBase, sql.DictBase): __tablename__ = 'user' attributes = ['id', 'name', 'domain_id', 'password', 'enabled', 'default_project_id'] id = sql.Column(sql.String(64), primary_key=True) name = sql.Column(sql.String(255), nullable=False) domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'), nullable=False) password = sql.Column(sql.String(128)) enabled = sql.Column(sql.Boolean) extra = sql.Column(sql.JsonBlob()) default_project_id = sql.Column(sql.String(64)) # Unique constraint across two columns to create the separation # rather than just only 'name' being unique __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {}) def to_dict(self, include_extra_dict=False): d = super(User, self).to_dict(include_extra_dict=include_extra_dict) if 'default_project_id' in d and d['default_project_id'] is None: del d['default_project_id'] return d class Group(sql.ModelBase, sql.DictBase): __tablename__ = 'group' attributes = ['id', 'name', 'domain_id', 'description'] id = sql.Column(sql.String(64), primary_key=True) name = sql.Column(sql.String(64), nullable=False) domain_id = sql.Column(sql.String(64), sql.ForeignKey('domain.id'), nullable=False) description = sql.Column(sql.Text()) extra = sql.Column(sql.JsonBlob()) # Unique constraint across two columns to create the separation # rather than just only 'name' being unique __table_args__ = (sql.UniqueConstraint('domain_id', 'name'), {}) class UserGroupMembership(sql.ModelBase, sql.DictBase): """Group membership join table.""" __tablename__ = 'user_group_membership' user_id = sql.Column(sql.String(64), sql.ForeignKey('user.id'), primary_key=True) group_id = sql.Column(sql.String(64), sql.ForeignKey('group.id'), primary_key=True) @dependency.requires('assignment_api') class Identity(identity.Driver): def default_assignment_driver(self): return "keystone.assignment.backends.sql.Assignment" # Internal interface to manage the database def db_sync(self, version=None): migration.db_sync( sql.get_engine(), migration_helpers.find_migrate_repo(), version=version) def _check_password(self, password, user_ref): """Check the specified password against the data store. This is modeled on ldap/core.py. The idea is to make it easier to subclass Identity so that you can still use it to store all the data, but use some other means to check the password. Note that we'll pass in the entire user_ref in case the subclass needs things like user_ref.get('name') For further justification, please see the follow up suggestion at https://blueprints.launchpad.net/keystone/+spec/sql-identiy-pam """ return utils.check_password(password, user_ref.password) def is_domain_aware(self): return True # Identity interface def authenticate(self, user_id, password): session = sql.get_session() user_ref = None try: user_ref = self._get_user(session, user_id) except exception.UserNotFound: raise AssertionError(_('Invalid user / password')) if not self._check_password(password, user_ref): raise AssertionError(_('Invalid user / password')) return identity.filter_user(user_ref.to_dict()) # user crud @sql.handle_conflicts(conflict_type='user') def create_user(self, user_id, user): user = utils.hash_user_password(user) session = sql.get_session() with session.begin(): user_ref = User.from_dict(user) session.add(user_ref) return identity.filter_user(user_ref.to_dict()) @sql.truncated def list_users(self, hints): session = sql.get_session() query = session.query(User) user_refs = sql.filter_limit_query(User, query, hints) return [identity.filter_user(x.to_dict()) for x in user_refs] def _get_user(self, session, user_id): user_ref = session.query(User).get(user_id) if not user_ref: raise exception.UserNotFound(user_id=user_id) return user_ref def get_user(self, user_id): session = sql.get_session() return identity.filter_user(self._get_user(session, user_id).to_dict()) def get_user_by_name(self, user_name, domain_id): session = sql.get_session() query = session.query(User) query = query.filter_by(name=user_name) query = query.filter_by(domain_id=domain_id) try: user_ref = query.one() except sql.NotFound: raise exception.UserNotFound(user_id=user_name) return identity.filter_user(user_ref.to_dict()) @sql.handle_conflicts(conflict_type='user') def update_user(self, user_id, user): session = sql.get_session() if 'id' in user and user_id != user['id']: raise exception.ValidationError(_('Cannot change user ID')) with session.begin(): user_ref = self._get_user(session, user_id) old_user_dict = user_ref.to_dict() user = utils.hash_user_password(user) for k in user: old_user_dict[k] = user[k] new_user = User.from_dict(old_user_dict) for attr in User.attributes: if attr != 'id': setattr(user_ref, attr, getattr(new_user, attr)) user_ref.extra = new_user.extra return identity.filter_user(user_ref.to_dict(include_extra_dict=True)) def add_user_to_group(self, user_id, group_id): session = sql.get_session() self.get_group(group_id) self.get_user(user_id) query = session.query(UserGroupMembership) query = query.filter_by(user_id=user_id) query = query.filter_by(group_id=group_id) rv = query.first() if rv: return with session.begin(): session.add(UserGroupMembership(user_id=user_id, group_id=group_id)) def check_user_in_group(self, user_id, group_id): session = sql.get_session() self.get_group(group_id) self.get_user(user_id) query = session.query(UserGroupMembership) query = query.filter_by(user_id=user_id) query = query.filter_by(group_id=group_id) if not query.first(): raise exception.NotFound(_('User not found in group')) def remove_user_from_group(self, user_id, group_id): session = sql.get_session() # We don't check if user or group are still valid and let the remove # be tried anyway - in case this is some kind of clean-up operation query = session.query(UserGroupMembership) query = query.filter_by(user_id=user_id) query = query.filter_by(group_id=group_id) membership_ref = query.first() if membership_ref is None: raise exception.NotFound(_('User not found in group')) with session.begin(): session.delete(membership_ref) def list_groups_for_user(self, user_id, hints): # TODO(henry-nash) We could implement full filtering here by enhancing # the join below. However, since it is likely to be a fairly rare # occurrence to filter on more than the user_id already being used # here, this is left as future enhancement and until then we leave # it for the controller to do for us. session = sql.get_session() self.get_user(user_id) query = session.query(Group).join(UserGroupMembership) query = query.filter(UserGroupMembership.user_id == user_id) return [g.to_dict() for g in query] def list_users_in_group(self, group_id, hints): # TODO(henry-nash) We could implement full filtering here by enhancing # the join below. However, since it is likely to be a fairly rare # occurrence to filter on more than the group_id already being used # here, this is left as future enhancement and until then we leave # it for the controller to do for us. session = sql.get_session() self.get_group(group_id) query = session.query(User).join(UserGroupMembership) query = query.filter(UserGroupMembership.group_id == group_id) return [identity.filter_user(u.to_dict()) for u in query] def delete_user(self, user_id): session = sql.get_session() with session.begin(): ref = self._get_user(session, user_id) q = session.query(UserGroupMembership) q = q.filter_by(user_id=user_id) q.delete(False) session.delete(ref) self.assignment_api.delete_user(user_id) # group crud @sql.handle_conflicts(conflict_type='group') def create_group(self, group_id, group): session = sql.get_session() with session.begin(): ref = Group.from_dict(group) session.add(ref) return ref.to_dict() @sql.truncated def list_groups(self, hints): session = sql.get_session() query = session.query(Group) refs = sql.filter_limit_query(Group, query, hints) return [ref.to_dict() for ref in refs] def _get_group(self, session, group_id): ref = session.query(Group).get(group_id) if not ref: raise exception.GroupNotFound(group_id=group_id) return ref def get_group(self, group_id): session = sql.get_session() return self._get_group(session, group_id).to_dict() @sql.handle_conflicts(conflict_type='group') def update_group(self, group_id, group): session = sql.get_session() with session.begin(): ref = self._get_group(session, group_id) old_dict = ref.to_dict() for k in group: old_dict[k] = group[k] new_group = Group.from_dict(old_dict) for attr in Group.attributes: if attr != 'id': setattr(ref, attr, getattr(new_group, attr)) ref.extra = new_group.extra return ref.to_dict() def delete_group(self, group_id): session = sql.get_session() with session.begin(): ref = self._get_group(session, group_id) q = session.query(UserGroupMembership) q = q.filter_by(group_id=group_id) q.delete(False) session.delete(ref) self.assignment_api.delete_group(group_id) keystone-2014.1/keystone/identity/backends/ldap.py0000664000175400017540000003170312323716267023353 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from __future__ import absolute_import import uuid import ldap import ldap.filter from keystone import clean from keystone.common import dependency from keystone.common import driver_hints from keystone.common import ldap as common_ldap from keystone.common import models from keystone.common import utils from keystone import config from keystone import exception from keystone import identity from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import log CONF = config.CONF LOG = log.getLogger(__name__) @dependency.requires('assignment_api') class Identity(identity.Driver): def __init__(self, conf=None): super(Identity, self).__init__() if conf is None: conf = CONF self.user = UserApi(conf) self.group = GroupApi(conf) def default_assignment_driver(self): return "keystone.assignment.backends.ldap.Assignment" def is_domain_aware(self): return False # Identity interface def authenticate(self, user_id, password): try: user_ref = self._get_user(user_id) except exception.UserNotFound: raise AssertionError(_('Invalid user / password')) if not user_id or not password: raise AssertionError(_('Invalid user / password')) conn = None try: conn = self.user.get_connection(self.user._id_to_dn(user_id), password) if not conn: raise AssertionError(_('Invalid user / password')) except Exception: raise AssertionError(_('Invalid user / password')) finally: if conn: conn.unbind_s() return identity.filter_user(user_ref) def _get_user(self, user_id): return self.user.get(user_id) def get_user(self, user_id): return identity.filter_user(self._get_user(user_id)) def list_users(self, hints): return self.user.get_all_filtered() def get_user_by_name(self, user_name, domain_id): # domain_id will already have been handled in the Manager layer, # parameter left in so this matches the Driver specification return identity.filter_user(self.user.get_by_name(user_name)) # CRUD def create_user(self, user_id, user): self.user.check_allow_create() user_ref = self.user.create(user) return identity.filter_user(user_ref) def update_user(self, user_id, user): self.user.check_allow_update() if 'id' in user and user['id'] != user_id: raise exception.ValidationError(_('Cannot change user ID')) old_obj = self.user.get(user_id) if 'name' in user and old_obj.get('name') != user['name']: raise exception.Conflict(_('Cannot change user name')) user = utils.hash_ldap_user_password(user) if self.user.enabled_mask: self.user.mask_enabled_attribute(user) self.user.update(user_id, user, old_obj) return self.user.get_filtered(user_id) def delete_user(self, user_id): self.user.check_allow_delete() self.assignment_api.delete_user(user_id) user_dn = self.user._id_to_dn(user_id) groups = self.group.list_user_groups(user_dn) for group in groups: self.group.remove_user(user_dn, group['id'], user_id) user = self.user.get(user_id) if hasattr(user, 'tenant_id'): self.project.remove_user(user.tenant_id, self.user._id_to_dn(user_id)) self.user.delete(user_id) def create_group(self, group_id, group): self.group.check_allow_create() group['name'] = clean.group_name(group['name']) return self.group.create(group) def get_group(self, group_id): return self.group.get(group_id) def update_group(self, group_id, group): self.group.check_allow_update() if 'name' in group: group['name'] = clean.group_name(group['name']) return self.group.update(group_id, group) def delete_group(self, group_id): self.group.check_allow_delete() return self.group.delete(group_id) def add_user_to_group(self, user_id, group_id): self.get_user(user_id) self.get_group(group_id) user_dn = self.user._id_to_dn(user_id) self.group.add_user(user_dn, group_id, user_id) def remove_user_from_group(self, user_id, group_id): self.get_user(user_id) self.get_group(group_id) user_dn = self.user._id_to_dn(user_id) self.group.remove_user(user_dn, group_id, user_id) def list_groups_for_user(self, user_id, hints): self.get_user(user_id) user_dn = self.user._id_to_dn(user_id) return self.group.list_user_groups(user_dn) def list_groups(self, hints): return self.group.get_all() def list_users_in_group(self, group_id, hints): self.get_group(group_id) users = [] for user_dn in self.group.list_group_users(group_id): user_id = self.user._dn_to_id(user_dn) try: users.append(self.user.get_filtered(user_id)) except exception.UserNotFound: LOG.debug(_("Group member '%(user_dn)s' not found in" " '%(group_id)s'. The user should be removed" " from the group. The user will be ignored."), dict(user_dn=user_dn, group_id=group_id)) return users def check_user_in_group(self, user_id, group_id): self.get_user(user_id) self.get_group(group_id) user_refs = self.list_users_in_group(group_id, driver_hints.Hints()) found = False for x in user_refs: if x['id'] == user_id: found = True break if not found: raise exception.NotFound(_('User not found in group')) # TODO(termie): turn this into a data object and move logic to driver class UserApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap): DEFAULT_OU = 'ou=Users' DEFAULT_STRUCTURAL_CLASSES = ['person'] DEFAULT_ID_ATTR = 'cn' DEFAULT_OBJECTCLASS = 'inetOrgPerson' NotFound = exception.UserNotFound options_name = 'user' attribute_options_names = {'password': 'pass', 'email': 'mail', 'name': 'name', 'enabled': 'enabled', 'default_project_id': 'default_project_id'} immutable_attrs = ['id'] model = models.User def __init__(self, conf): super(UserApi, self).__init__(conf) self.enabled_mask = conf.ldap.user_enabled_mask self.enabled_default = conf.ldap.user_enabled_default def _ldap_res_to_model(self, res): obj = super(UserApi, self)._ldap_res_to_model(res) if self.enabled_mask != 0: enabled = int(obj.get('enabled', self.enabled_default)) obj['enabled'] = ((enabled & self.enabled_mask) != self.enabled_mask) return obj def mask_enabled_attribute(self, values): value = values['enabled'] values.setdefault('enabled_nomask', int(self.enabled_default)) if value != ((values['enabled_nomask'] & self.enabled_mask) != self.enabled_mask): values['enabled_nomask'] ^= self.enabled_mask values['enabled'] = values['enabled_nomask'] del values['enabled_nomask'] def create(self, values): values = utils.hash_ldap_user_password(values) if self.enabled_mask: orig_enabled = values['enabled'] self.mask_enabled_attribute(values) values = super(UserApi, self).create(values) if self.enabled_mask: values['enabled'] = orig_enabled return values def check_password(self, user_id, password): user = self.get(user_id) return utils.check_password(password, user.password) def get_filtered(self, user_id): user = self.get(user_id) return identity.filter_user(user) def get_all_filtered(self): return [identity.filter_user(user) for user in self.get_all()] class GroupApi(common_ldap.BaseLdap): DEFAULT_OU = 'ou=UserGroups' DEFAULT_STRUCTURAL_CLASSES = [] DEFAULT_OBJECTCLASS = 'groupOfNames' DEFAULT_ID_ATTR = 'cn' DEFAULT_MEMBER_ATTRIBUTE = 'member' NotFound = exception.GroupNotFound options_name = 'group' attribute_options_names = {'description': 'desc', 'name': 'name'} immutable_attrs = ['name'] model = models.Group def __init__(self, conf): super(GroupApi, self).__init__(conf) self.member_attribute = (getattr(conf.ldap, 'group_member_attribute') or self.DEFAULT_MEMBER_ATTRIBUTE) def create(self, values): data = values.copy() if data.get('id') is None: data['id'] = uuid.uuid4().hex if 'description' in data and data['description'] in ['', None]: data.pop('description') return super(GroupApi, self).create(data) def delete(self, group_id): if self.subtree_delete_enabled: super(GroupApi, self).deleteTree(group_id) else: # TODO(spzala): this is only placeholder for group and domain # role support which will be added under bug 1101287 query = '(objectClass=%s)' % self.object_class dn = None dn = self._id_to_dn(group_id) if dn: try: conn = self.get_connection() roles = conn.search_s(dn, ldap.SCOPE_ONELEVEL, query, ['%s' % '1.1']) for role_dn, _ in roles: conn.delete_s(role_dn) except ldap.NO_SUCH_OBJECT: pass finally: conn.unbind_s() super(GroupApi, self).delete(group_id) def update(self, group_id, values): old_obj = self.get(group_id) return super(GroupApi, self).update(group_id, values, old_obj) def add_user(self, user_dn, group_id, user_id): conn = self.get_connection() try: conn.modify_s( self._id_to_dn(group_id), [(ldap.MOD_ADD, self.member_attribute, user_dn)]) except ldap.TYPE_OR_VALUE_EXISTS: raise exception.Conflict(_( 'User %(user_id)s is already a member of group %(group_id)s') % {'user_id': user_id, 'group_id': group_id}) finally: conn.unbind_s() def remove_user(self, user_dn, group_id, user_id): conn = self.get_connection() try: conn.modify_s( self._id_to_dn(group_id), [(ldap.MOD_DELETE, self.member_attribute, user_dn)]) except ldap.NO_SUCH_ATTRIBUTE: raise exception.UserNotFound(user_id=user_id) finally: conn.unbind_s() def list_user_groups(self, user_dn): """Return a list of groups for which the user is a member.""" user_dn_esc = ldap.filter.escape_filter_chars(user_dn) query = '(&(objectClass=%s)(%s=%s)%s)' % (self.object_class, self.member_attribute, user_dn_esc, self.ldap_filter or '') memberships = self.get_all(query) return memberships def list_group_users(self, group_id): """Return a list of user dns which are members of a group.""" query = '(objectClass=%s)' % self.object_class conn = self.get_connection() group_dn = self._id_to_dn(group_id) try: attrs = conn.search_s(group_dn, ldap.SCOPE_BASE, query, ['%s' % self.member_attribute]) except ldap.NO_SUCH_OBJECT: return [] finally: conn.unbind_s() users = [] for dn, member in attrs: user_dns = member.get(self.member_attribute, []) for user_dn in user_dns: if self.use_dumb_member and user_dn == self.dumb_member: continue users.append(user_dn) return users keystone-2014.1/keystone/identity/backends/kvs.py0000664000175400017540000002537612323716267023247 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. from keystone.common import kvs from keystone.common import utils from keystone import exception from keystone import identity from keystone.openstack.common.gettextutils import _ class _UserIdToDomainId(object): """User ID to domain ID mapping. Stores the user ID to domain ID mapping so that the domain for a user can be looked up quickly. """ def __init__(self, db): self.db = db def _calc_key(self, user_id): """Calculate the key name for the "user ID to domain ID" field.""" return ('user_domain-%s' % (user_id)) def notify_user_created(self, user_id, domain_id): """Indicates that a user was created.""" self.db.set(self._calc_key(user_id), domain_id) def notify_user_deleted(self, user_id): """Indicates that a user was deleted. This needs to be called when a user is deleted to keep the database clean. """ self.db.delete(self._calc_key(user_id)) def get(self, user_id): """Return the domain ID for a user.""" return self.db.get(self._calc_key(user_id)) class Identity(kvs.Base, identity.Driver): def __init__(self): super(Identity, self).__init__() self._user_id_to_domain_id = _UserIdToDomainId(self.db) def default_assignment_driver(self): return "keystone.assignment.backends.kvs.Assignment" def is_domain_aware(self): return True # Public interface def authenticate(self, user_id, password): user_ref = None try: user_ref = self._get_user(user_id) except exception.UserNotFound: raise AssertionError(_('Invalid user / password')) if not utils.check_password(password, user_ref.get('password')): raise AssertionError(_('Invalid user / password')) return identity.filter_user(user_ref) def _get_user(self, user_id): try: return self.db.get('user-%s' % user_id) except exception.NotFound: raise exception.UserNotFound(user_id=user_id) def _calc_user_name_key(self, name, domain_id): """Calculate the name of the "user name" key. Calculates the name of the key used to store the mapping of user name and domain to user ID. This allows quick lookup of the user ID given a user name and domain ID. """ return ('user_name-%s-%s' % (domain_id, name)) def _get_user_by_name(self, user_name, domain_id): try: return self.db.get(self._calc_user_name_key(user_name, domain_id)) except exception.NotFound: raise exception.UserNotFound(user_id=user_name) def get_user(self, user_id): return identity.filter_user(self._get_user(user_id)) def get_user_by_name(self, user_name, domain_id): return identity.filter_user( self._get_user_by_name(user_name, domain_id)) def list_users(self, hints): user_ids = self.db.get('user_list', []) return [self.get_user(x) for x in user_ids] # CRUD def create_user(self, user_id, user): try: self.get_user(user_id) except exception.UserNotFound: pass else: msg = _('Duplicate ID, %s.') % user_id raise exception.Conflict(type='user', details=msg) try: self.get_user_by_name(user['name'], user['domain_id']) except exception.UserNotFound: pass else: msg = _('Duplicate name, %s.') % user['name'] raise exception.Conflict(type='user', details=msg) user = utils.hash_user_password(user) new_user = user.copy() new_user.setdefault('groups', []) self.db.set('user-%s' % user_id, new_user) domain_id = user['domain_id'] user_name_key = self._calc_user_name_key(new_user['name'], domain_id) self.db.set(user_name_key, new_user) self._user_id_to_domain_id.notify_user_created(user_id, domain_id) user_list = set(self.db.get('user_list', [])) user_list.add(user_id) self.db.set('user_list', list(user_list)) return identity.filter_user(new_user) def update_user(self, user_id, user): try: domain_id = self._user_id_to_domain_id.get(user_id) except exception.NotFound: raise exception.UserNotFound(user_id=user_id) if 'name' in user: user_key = self._calc_user_name_key(user['name'], domain_id) existing = self.db.get(user_key, False) if existing and user_id != existing['id']: msg = _('Duplicate name, %s.') % user['name'] raise exception.Conflict(type='user', details=msg) # get the old name and delete it too old_user = self.db.get('user-%s' % user_id) new_user = old_user.copy() user = utils.hash_user_password(user) new_user.update(user) if new_user['id'] != user_id: raise exception.ValidationError('Cannot change user ID') self.db.delete(self._calc_user_name_key(old_user['name'], domain_id)) self.db.set('user-%s' % user_id, new_user) user_name_key = self._calc_user_name_key(new_user['name'], domain_id) self.db.set(user_name_key, new_user) return identity.filter_user(new_user) def add_user_to_group(self, user_id, group_id): self.get_group(group_id) user_ref = self._get_user(user_id) groups = set(user_ref.get('groups', [])) groups.add(group_id) self.update_user(user_id, {'groups': list(groups)}) def check_user_in_group(self, user_id, group_id): self.get_group(group_id) user_ref = self._get_user(user_id) if group_id not in set(user_ref.get('groups', [])): raise exception.NotFound(_('User not found in group')) def remove_user_from_group(self, user_id, group_id): self.get_group(group_id) user_ref = self._get_user(user_id) groups = set(user_ref.get('groups', [])) try: groups.remove(group_id) except KeyError: raise exception.NotFound(_('User not found in group')) self.update_user(user_id, {'groups': list(groups)}) def list_users_in_group(self, group_id, hints): self.get_group(group_id) user_keys = (k for k in self.db.keys() if k.startswith('user-')) user_refs = (self.db.get(key) for key in user_keys) user_refs_for_group = (ref for ref in user_refs if group_id in ref['groups']) return [identity.filter_user(x) for x in user_refs_for_group] def list_groups_for_user(self, user_id, hints): user_ref = self._get_user(user_id) group_ids = user_ref.get('groups', []) return [self.get_group(x) for x in group_ids] def delete_user(self, user_id): try: old_user = self.db.get('user-%s' % user_id) except exception.NotFound: raise exception.UserNotFound(user_id=user_id) domain_id = self._user_id_to_domain_id.get(user_id) self.db.delete(self._calc_user_name_key(old_user['name'], domain_id)) self.db.delete('user-%s' % user_id) self._user_id_to_domain_id.notify_user_deleted(user_id) user_list = set(self.db.get('user_list', [])) user_list.remove(user_id) self.db.set('user_list', list(user_list)) # group crud def create_group(self, group_id, group): try: return self.db.get('group-%s' % group_id) except exception.NotFound: pass else: msg = _('Duplicate ID, %s.') % group_id raise exception.Conflict(type='group', details=msg) try: self.db.get('group_name-%s' % group['name']) except exception.NotFound: pass else: msg = _('Duplicate name, %s.') % group['name'] raise exception.Conflict(type='group', details=msg) self.db.set('group-%s' % group_id, group) self.db.set('group_name-%s' % group['name'], group) group_list = set(self.db.get('group_list', [])) group_list.add(group_id) self.db.set('group_list', list(group_list)) return group def list_groups(self, hints): group_ids = self.db.get('group_list', []) return [self.get_group(x) for x in group_ids] def get_group(self, group_id): try: return self.db.get('group-%s' % group_id) except exception.NotFound: raise exception.GroupNotFound(group_id=group_id) def update_group(self, group_id, group): # First, make sure we are not trying to change the # name to one that is already in use try: self.db.get('group_name-%s' % group['name']) except exception.NotFound: pass else: msg = _('Duplicate name, %s.') % group['name'] raise exception.Conflict(type='group', details=msg) # Now, get the old name and delete it try: old_group = self.db.get('group-%s' % group_id) except exception.NotFound: raise exception.GroupNotFound(group_id=group_id) self.db.delete('group_name-%s' % old_group['name']) # Finally, actually do the update self.db.set('group-%s' % group_id, group) self.db.set('group_name-%s' % group['name'], group) return group def delete_group(self, group_id): try: group = self.db.get('group-%s' % group_id) except exception.NotFound: raise exception.GroupNotFound(group_id=group_id) # Delete any entries in the group lists of all users user_keys = (k for k in self.db.keys() if k.startswith('user-')) user_refs = (self.db.get(key) for key in user_keys) for user_ref in user_refs: groups = set(user_ref.get('groups', [])) if group_id in groups: groups.remove(group_id) self.update_user(user_ref['id'], {'groups': list(groups)}) # Now delete the group itself self.db.delete('group-%s' % group_id) self.db.delete('group_name-%s' % group['name']) group_list = set(self.db.get('group_list', [])) group_list.remove(group_id) self.db.set('group_list', list(group_list)) keystone-2014.1/keystone/identity/backends/__init__.py0000664000175400017540000000000012323716267024154 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/identity/__init__.py0000664000175400017540000000131712323716272022412 0ustar jenkinsjenkins00000000000000# flake8: noqa # Copyright 2012 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. from keystone.identity import controllers from keystone.identity.core import * from keystone.identity import routers keystone-2014.1/keystone/__init__.py0000664000175400017540000000000012323716267020551 0ustar jenkinsjenkins00000000000000keystone-2014.1/keystone/clean.py0000664000175400017540000000520312323716267020106 0ustar jenkinsjenkins00000000000000# Copyright 2012 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. import six from keystone import exception from keystone.openstack.common.gettextutils import _ def check_length(property_name, value, min_length=1, max_length=64): if len(value) < min_length: if min_length == 1: msg = _("%s cannot be empty.") % property_name else: msg = (_("%(property_name)s cannot be less than " "%(min_length)s characters.") % dict( property_name=property_name, min_length=min_length)) raise exception.ValidationError(msg) if len(value) > max_length: msg = (_("%(property_name)s should not be greater than " "%(max_length)s characters.") % dict( property_name=property_name, max_length=max_length)) raise exception.ValidationError(msg) def check_type(property_name, value, expected_type, display_expected_type): if not isinstance(value, expected_type): msg = (_("%(property_name)s is not a " "%(display_expected_type)s") % dict( property_name=property_name, display_expected_type=display_expected_type)) raise exception.ValidationError(msg) def check_enabled(property_name, enabled): # Allow int and it's subclass bool check_type('%s enabled' % property_name, enabled, int, 'boolean') return bool(enabled) def check_name(property_name, name, min_length=1, max_length=64): check_type('%s name' % property_name, name, six.string_types, 'str or unicode') name = name.strip() check_length('%s name' % property_name, name, min_length=min_length, max_length=max_length) return name def domain_name(name): return check_name('Domain', name) def project_name(name): return check_name('Project', name) def project_enabled(enabled): return check_enabled('Project', enabled) def user_name(name): return check_name('User', name, max_length=255) def user_enabled(enabled): return check_enabled('User', enabled) def group_name(name): return check_name('Group', name) keystone-2014.1/setup.cfg0000664000175400017540000000250412323716511016423 0ustar jenkinsjenkins00000000000000[metadata] name = keystone version = 2014.1 summary = OpenStack Identity description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = http://www.openstack.org/ classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.6 [files] packages = keystone scripts = bin/keystone-all bin/keystone-manage [global] setup-hooks = pbr.hooks.setup_hook [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [build_sphinx] all_files = 1 build-dir = doc/build source-dir = doc/source [compile_catalog] directory = keystone/locale domain = keystone [update_catalog] domain = keystone output_dir = keystone/locale input_file = keystone/locale/keystone.pot [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = keystone/locale/keystone.pot copyright_holder = OpenStack Foundation msgid_bugs_address = https://bugs.launchpad.net/keystone [pbr] warnerrors = True [entry_points] oslo.config.opts = keystone = keystone.common.config:list_opts keystone-2014.1/setup.py0000664000175400017540000000141512323716267016324 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools setuptools.setup( setup_requires=['pbr'], pbr=True) keystone-2014.1/tools/0000775000175400017540000000000012323716511015741 5ustar jenkinsjenkins00000000000000keystone-2014.1/tools/sample_data.sh0000775000175400017540000002157112323716267020570 0ustar jenkinsjenkins00000000000000#!/usr/bin/env bash # Copyright 2013 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. # Sample initial data for Keystone using python-keystoneclient # # This script is based on the original DevStack keystone_data.sh script. # # It demonstrates how to bootstrap Keystone with an administrative user # using the OS_SERVICE_TOKEN and OS_SERVICE_ENDPOINT environment variables # and the administrative API. It will get the admin_token (OS_SERVICE_TOKEN) # and admin_port from keystone.conf if available. # # Disable creation of endpoints by setting DISABLE_ENDPOINTS environment variable. # Use this with the Catalog Templated backend. # # A EC2-compatible credential is created for the admin user and # placed in etc/ec2rc. # # Tenant User Roles # ------------------------------------------------------- # demo admin admin # service glance admin # service nova admin # service ec2 admin # service swift admin # By default, passwords used are those in the OpenStack Install and Deploy Manual. # One can override these (publicly known, and hence, insecure) passwords by setting the appropriate # environment variables. A common default password for all the services can be used by # setting the "SERVICE_PASSWORD" environment variable. ADMIN_PASSWORD=${ADMIN_PASSWORD:-secrete} NOVA_PASSWORD=${NOVA_PASSWORD:-${SERVICE_PASSWORD:-nova}} GLANCE_PASSWORD=${GLANCE_PASSWORD:-${SERVICE_PASSWORD:-glance}} EC2_PASSWORD=${EC2_PASSWORD:-${SERVICE_PASSWORD:-ec2}} SWIFT_PASSWORD=${SWIFT_PASSWORD:-${SERVICE_PASSWORD:-swiftpass}} CONTROLLER_PUBLIC_ADDRESS=${CONTROLLER_PUBLIC_ADDRESS:-localhost} CONTROLLER_ADMIN_ADDRESS=${CONTROLLER_ADMIN_ADDRESS:-localhost} CONTROLLER_INTERNAL_ADDRESS=${CONTROLLER_INTERNAL_ADDRESS:-localhost} TOOLS_DIR=$(cd $(dirname "$0") && pwd) KEYSTONE_CONF=${KEYSTONE_CONF:-/etc/keystone/keystone.conf} if [[ -r "$KEYSTONE_CONF" ]]; then EC2RC="$(dirname "$KEYSTONE_CONF")/ec2rc" elif [[ -r "$TOOLS_DIR/../etc/keystone.conf" ]]; then # assume git checkout KEYSTONE_CONF="$TOOLS_DIR/../etc/keystone.conf" EC2RC="$TOOLS_DIR/../etc/ec2rc" else KEYSTONE_CONF="" EC2RC="ec2rc" fi # Extract some info from Keystone's configuration file if [[ -r "$KEYSTONE_CONF" ]]; then CONFIG_SERVICE_TOKEN=$(sed 's/[[:space:]]//g' $KEYSTONE_CONF | grep ^admin_token= | cut -d'=' -f2) CONFIG_ADMIN_PORT=$(sed 's/[[:space:]]//g' $KEYSTONE_CONF | grep ^admin_port= | cut -d'=' -f2) fi export OS_SERVICE_TOKEN=${OS_SERVICE_TOKEN:-$CONFIG_SERVICE_TOKEN} if [[ -z "$OS_SERVICE_TOKEN" ]]; then echo "No service token found." echo "Set OS_SERVICE_TOKEN manually from keystone.conf admin_token." exit 1 fi export OS_SERVICE_ENDPOINT=${OS_SERVICE_ENDPOINT:-http://$CONTROLLER_PUBLIC_ADDRESS:${CONFIG_ADMIN_PORT:-35357}/v2.0} function get_id () { echo `"$@" | grep ' id ' | awk '{print $4}'` } # # Default tenant # DEMO_TENANT=$(get_id keystone tenant-create --name=demo \ --description "Default Tenant") ADMIN_USER=$(get_id keystone user-create --name=admin \ --pass="${ADMIN_PASSWORD}") ADMIN_ROLE=$(get_id keystone role-create --name=admin) keystone user-role-add --user-id $ADMIN_USER \ --role-id $ADMIN_ROLE \ --tenant-id $DEMO_TENANT # # Service tenant # SERVICE_TENANT=$(get_id keystone tenant-create --name=service \ --description "Service Tenant") GLANCE_USER=$(get_id keystone user-create --name=glance \ --pass="${GLANCE_PASSWORD}") keystone user-role-add --user-id $GLANCE_USER \ --role-id $ADMIN_ROLE \ --tenant-id $SERVICE_TENANT NOVA_USER=$(get_id keystone user-create --name=nova \ --pass="${NOVA_PASSWORD}" \ --tenant-id $SERVICE_TENANT) keystone user-role-add --user-id $NOVA_USER \ --role-id $ADMIN_ROLE \ --tenant-id $SERVICE_TENANT EC2_USER=$(get_id keystone user-create --name=ec2 \ --pass="${EC2_PASSWORD}" \ --tenant-id $SERVICE_TENANT) keystone user-role-add --user-id $EC2_USER \ --role-id $ADMIN_ROLE \ --tenant-id $SERVICE_TENANT SWIFT_USER=$(get_id keystone user-create --name=swift \ --pass="${SWIFT_PASSWORD}" \ --tenant-id $SERVICE_TENANT) keystone user-role-add --user-id $SWIFT_USER \ --role-id $ADMIN_ROLE \ --tenant-id $SERVICE_TENANT # # Keystone service # KEYSTONE_SERVICE=$(get_id \ keystone service-create --name=keystone \ --type=identity \ --description="Keystone Identity Service") if [[ -z "$DISABLE_ENDPOINTS" ]]; then keystone endpoint-create --region RegionOne --service-id $KEYSTONE_SERVICE \ --publicurl "http://$CONTROLLER_PUBLIC_ADDRESS:\$(public_port)s/v2.0" \ --adminurl "http://$CONTROLLER_ADMIN_ADDRESS:\$(admin_port)s/v2.0" \ --internalurl "http://$CONTROLLER_INTERNAL_ADDRESS:\$(public_port)s/v2.0" fi # # Nova service # NOVA_SERVICE=$(get_id \ keystone service-create --name=nova \ --type=compute \ --description="Nova Compute Service") if [[ -z "$DISABLE_ENDPOINTS" ]]; then keystone endpoint-create --region RegionOne --service-id $NOVA_SERVICE \ --publicurl "http://$CONTROLLER_PUBLIC_ADDRESS:\$(compute_port)s/v2/\$(tenant_id)s" \ --adminurl "http://$CONTROLLER_ADMIN_ADDRESS:\$(compute_port)s/v2/\$(tenant_id)s" \ --internalurl "http://$CONTROLLER_INTERNAL_ADDRESS:\$(compute_port)s/v2/\$(tenant_id)s" fi # # Volume service # VOLUME_SERVICE=$(get_id \ keystone service-create --name=volume \ --type=volume \ --description="Nova Volume Service") if [[ -z "$DISABLE_ENDPOINTS" ]]; then keystone endpoint-create --region RegionOne --service-id $VOLUME_SERVICE \ --publicurl "http://$CONTROLLER_PUBLIC_ADDRESS:8776/v1/\$(tenant_id)s" \ --adminurl "http://$CONTROLLER_ADMIN_ADDRESS:8776/v1/\$(tenant_id)s" \ --internalurl "http://$CONTROLLER_INTERNAL_ADDRESS:8776/v1/\$(tenant_id)s" fi # # Image service # GLANCE_SERVICE=$(get_id \ keystone service-create --name=glance \ --type=image \ --description="Glance Image Service") if [[ -z "$DISABLE_ENDPOINTS" ]]; then keystone endpoint-create --region RegionOne --service-id $GLANCE_SERVICE \ --publicurl "http://$CONTROLLER_PUBLIC_ADDRESS:9292" \ --adminurl "http://$CONTROLLER_ADMIN_ADDRESS:9292" \ --internalurl "http://$CONTROLLER_INTERNAL_ADDRESS:9292" fi # # EC2 service # EC2_SERVICE=$(get_id \ keystone service-create --name=ec2 \ --type=ec2 \ --description="EC2 Compatibility Layer") if [[ -z "$DISABLE_ENDPOINTS" ]]; then keystone endpoint-create --region RegionOne --service-id $EC2_SERVICE \ --publicurl "http://$CONTROLLER_PUBLIC_ADDRESS:8773/services/Cloud" \ --adminurl "http://$CONTROLLER_ADMIN_ADDRESS:8773/services/Admin" \ --internalurl "http://$CONTROLLER_INTERNAL_ADDRESS:8773/services/Cloud" fi # # Swift service # SWIFT_SERVICE=$(get_id \ keystone service-create --name=swift \ --type="object-store" \ --description="Swift Service") if [[ -z "$DISABLE_ENDPOINTS" ]]; then keystone endpoint-create --region RegionOne --service-id $SWIFT_SERVICE \ --publicurl "http://$CONTROLLER_PUBLIC_ADDRESS:8080/v1/AUTH_\$(tenant_id)s" \ --adminurl "http://$CONTROLLER_ADMIN_ADDRESS:8080/v1" \ --internalurl "http://$CONTROLLER_INTERNAL_ADDRESS:8080/v1/AUTH_\$(tenant_id)s" fi # create ec2 creds and parse the secret and access key returned RESULT=$(keystone ec2-credentials-create --tenant-id=$SERVICE_TENANT --user-id=$ADMIN_USER) ADMIN_ACCESS=`echo "$RESULT" | grep access | awk '{print $4}'` ADMIN_SECRET=`echo "$RESULT" | grep secret | awk '{print $4}'` # write the secret and access to ec2rc cat > $EC2RC <&2 } PARSED_OPTIONS=$(getopt -n "${0##*/}" -o hb:p:m:l:o: \ --long help,base-dir:,package-name:,output-dir:,module:,library: -- "$@") if [ $? != 0 ] ; then print_hint ; exit 1 ; fi eval set -- "$PARSED_OPTIONS" while true; do case "$1" in -h|--help) echo "${0##*/} [options]" echo "" echo "options:" echo "-h, --help show brief help" echo "-b, --base-dir=DIR project base directory" echo "-p, --package-name=NAME project package name" echo "-o, --output-dir=DIR file output directory" echo "-m, --module=MOD extra python module to interrogate for options" echo "-l, --library=LIB extra library that registers options for discovery" exit 0 ;; -b|--base-dir) shift BASEDIR=`echo $1 | sed -e 's/\/*$//g'` shift ;; -p|--package-name) shift PACKAGENAME=`echo $1` shift ;; -o|--output-dir) shift OUTPUTDIR=`echo $1 | sed -e 's/\/*$//g'` shift ;; -m|--module) shift MODULES="$MODULES -m $1" shift ;; -l|--library) shift LIBRARIES="$LIBRARIES -l $1" shift ;; --) break ;; esac done BASEDIR=${BASEDIR:-`pwd`} if ! [ -d $BASEDIR ] then echo "${0##*/}: missing project base directory" >&2 ; print_hint ; exit 1 elif [[ $BASEDIR != /* ]] then BASEDIR=$(cd "$BASEDIR" && pwd) fi PACKAGENAME=${PACKAGENAME:-${BASEDIR##*/}} TARGETDIR=$BASEDIR/$PACKAGENAME if ! [ -d $TARGETDIR ] then echo "${0##*/}: invalid project package name" >&2 ; print_hint ; exit 1 fi OUTPUTDIR=${OUTPUTDIR:-$BASEDIR/etc} # NOTE(bnemec): Some projects put their sample config in etc/, # some in etc/$PACKAGENAME/ if [ -d $OUTPUTDIR/$PACKAGENAME ] then OUTPUTDIR=$OUTPUTDIR/$PACKAGENAME elif ! [ -d $OUTPUTDIR ] then echo "${0##*/}: cannot access \`$OUTPUTDIR': No such file or directory" >&2 exit 1 fi BASEDIRESC=`echo $BASEDIR | sed -e 's/\//\\\\\//g'` find $TARGETDIR -type f -name "*.pyc" -delete FILES=$(find $TARGETDIR -type f -name "*.py" ! -path "*/tests/*" \ -exec grep -l "Opt(" {} + | sed -e "s/^$BASEDIRESC\///g" | sort -u) RC_FILE="`dirname $0`/oslo.config.generator.rc" if test -r "$RC_FILE" then source "$RC_FILE" fi for mod in ${KEYSTONE_CONFIG_GENERATOR_EXTRA_MODULES}; do MODULES="$MODULES -m $mod" done for lib in ${KEYSTONE_CONFIG_GENERATOR_EXTRA_LIBRARIES}; do LIBRARIES="$LIBRARIES -l $lib" done export EVENTLET_NO_GREENDNS=yes OS_VARS=$(set | sed -n '/^OS_/s/=[^=]*$//gp' | xargs) [ "$OS_VARS" ] && eval "unset \$OS_VARS" DEFAULT_MODULEPATH=keystone.openstack.common.config.generator MODULEPATH=${MODULEPATH:-$DEFAULT_MODULEPATH} OUTPUTFILE=$OUTPUTDIR/$PACKAGENAME.conf.sample python -m $MODULEPATH $MODULES $LIBRARIES $FILES > $OUTPUTFILE # Hook to allow projects to append custom config file snippets CONCAT_FILES=$(ls $BASEDIR/tools/config/*.conf.sample 2>/dev/null) for CONCAT_FILE in $CONCAT_FILES; do cat $CONCAT_FILE >> $OUTPUTFILE done keystone-2014.1/tools/config/README0000664000175400017540000000241612323716267020101 0ustar jenkinsjenkins00000000000000This generate_sample.sh tool is used to generate sample config files from OpenStack project source trees. Run it by passing the base directory and package name i.e. $> generate_sample.sh --base-dir /opt/stack/nova --package-name nova \ --output-dir /opt/stack/nova/etc $> generate_sample.sh -b /opt/stack/neutron -p nova -o /opt/stack/neutron/etc Optionally, include libraries that register entry points for option discovery, such as oslo.messaging: $> generate_sample.sh -b /opt/stack/ceilometer -p ceilometer \ -o /opt/stack/ceilometer/etc -l oslo.messaging Watch out for warnings about modules like libvirt, qpid and zmq not being found - these warnings are significant because they result in options not appearing in the generated config file. This check_uptodate.sh tool is used to ensure that the generated sample config file in the OpenStack project source tree is continually kept up to date with the code itself. This can be done by adding a hook to tox.ini. For example, if a project already had flake8 enabled in a section like this: [testenv.pep8] commands = flake8 {posargs} This section would be changed to: [testenv.pep8] commands = flake8 {posargs} {toxinidir}/tools/config/check_uptodate.sh keystone-2014.1/tools/config/oslo.config.generator.rc0000664000175400017540000000042712323716267023754 0ustar jenkinsjenkins00000000000000# Environmental Variables that affect the automatic sample config generation. # Additions to any of these variables are space delimited. See the "generate_sample.sh" # script for the variables that can be used. KEYSTONE_CONFIG_GENERATOR_EXTRA_LIBRARIES='keystone oslo.messaging' keystone-2014.1/tools/config/check_uptodate.sh0000775000175400017540000000132512323716267022540 0ustar jenkinsjenkins00000000000000#!/usr/bin/env bash PROJECT_NAME=${PROJECT_NAME:-keystone} CFGFILE_NAME=${PROJECT_NAME}.conf.sample if [ -e etc/${PROJECT_NAME}/${CFGFILE_NAME} ]; then CFGFILE=etc/${PROJECT_NAME}/${CFGFILE_NAME} elif [ -e etc/${CFGFILE_NAME} ]; then CFGFILE=etc/${CFGFILE_NAME} else echo "${0##*/}: can not find config file" exit 1 fi TEMPDIR=`mktemp -d /tmp/${PROJECT_NAME}.XXXXXX` trap "rm -rf $TEMPDIR" EXIT tools/config/generate_sample.sh -b ./ -p ${PROJECT_NAME} -o ${TEMPDIR} if ! diff -u ${TEMPDIR}/${CFGFILE_NAME} ${CFGFILE} then echo "${0##*/}: ${PROJECT_NAME}.conf.sample is not up to date." echo "${0##*/}: Please run 'tox -esample_config -r' (see doc/source/developing.rst for more info)" exit 1 fi keystone-2014.1/tools/convert_to_sqlite.sh0000775000175400017540000000336612323716267022063 0ustar jenkinsjenkins00000000000000#!/bin/sh # ================================================================ # # Convert a mysql database dump into something sqlite3 understands. # # Adapted from # http://stackoverflow.com/questions/489277/script-to-convert-mysql-dump-sql-file-into-format-that-can-be-imported-into-sqlit # # (c) 2010 Martin Czygan # # ================================================================ if [ "$#" -lt 1 ]; then echo "Usage: $0 " exit fi SRC=$1 DST=$1.sqlite3.sql DB=$1.sqlite3.db ERR=$1.sqlite3.err cat $SRC | grep -v ' KEY "' | grep -v ' KEY `' | grep -v ' UNIQUE KEY "' | grep -v ' UNIQUE KEY `' | grep -v ' PRIMARY KEY ' | sed 's/ENGINE=MyISAM/ /g' | sed 's/DEFAULT/ /g' | sed 's/CHARSET=[a-zA-Z0-9]*/ /g' | sed 's/AUTO_INCREMENT=[0-9]*/ /g' | sed 's/\\r\\n/\\n/g' | sed 's/\\"/"/g' | sed '/^SET/d' | sed 's/ unsigned / /g' | sed 's/ auto_increment/ primary key autoincrement/g' | sed 's/ AUTO_INCREMENT/ primary key autoincrement/g' | sed 's/ smallint([0-9]*) / integer /g' | sed 's/ tinyint([0-9]*) / integer /g' | sed 's/ int([0-9]*) / integer /g' | sed 's/ character set [^ ]* / /g' | sed 's/ enum([^)]*) / varchar(255) /g' | sed 's/ on update [^,]*//g' | sed 's/UNLOCK TABLES;//g' | sed 's/LOCK TABLES [^;]*;//g' | perl -e 'local $/;$_=<>;s/,\n\)/\n\)/gs;print "begin;\n";print;print "commit;\n"' | perl -pe ' if (/^(INSERT.+?)\(/) { $a=$1; s/\\'\''/'\'\''/g; s/\\n/\n/g; s/\),\(/\);\n$a\(/g; } ' > $DST cat $DST | sqlite3 $DB > $ERR ERRORS=`cat $ERR | wc -l` if [ "$ERRORS" -eq "0" ]; then echo "Conversion completed without error. Your db is ready under: $DB" echo "\$ sqlite3 $DB" rm -f $ERR else echo "There were errors during conversion. \ Please review $ERR and $DST for details." fi keystone-2014.1/tools/install_venv.py0000664000175400017540000000443012323716267021030 0ustar jenkinsjenkins00000000000000# Copyright 2013 IBM Corp. # Copyright 2012 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """ virtualenv installation script """ import os import sys import install_venv_common as install_venv def print_help(): help = """ Keystone development environment setup is complete. Keystone development uses virtualenv to track and manage Python dependencies while in development and testing. To activate the Keystone virtualenv for the extent of your current shell session you can run: $ source .venv/bin/activate Or, if you prefer, you can run commands in the virtualenv on a case by case basis by running: $ tools/with_venv.sh Also, make test will automatically use the virtualenv. """ print help def main(argv): root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) venv = os.path.join(root, '.venv') pip_requires = os.path.join(root, 'requirements.txt') test_requires = os.path.join(root, 'test-requirements.txt') py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) project = 'Keystone' install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, py_version, project) options = install.parse_args(argv) install.check_python_version() install.check_dependencies() install.create_virtualenv(no_site_packages=options.no_site_packages) install.install_dependencies() install.run_command([os.path.join(venv, 'bin/python'), 'setup.py', 'develop']) print_help() if __name__ == '__main__': main(sys.argv) keystone-2014.1/tools/with_venv.sh0000775000175400017540000000033212323716267020317 0ustar jenkinsjenkins00000000000000#!/bin/bash TOOLS_PATH=${TOOLS_PATH:-$(dirname $0)} VENV_PATH=${VENV_PATH:-${TOOLS_PATH}} VENV_DIR=${VENV_NAME:-/../.venv} TOOLS=${TOOLS_PATH} VENV=${VENV:-${VENV_PATH}/${VENV_DIR}} source ${VENV}/bin/activate && "$@" keystone-2014.1/tools/colorizer.py0000775000175400017540000002735312323716267020350 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright (c) 2013, Nebula, Inc. # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. # # Colorizer Code is borrowed from Twisted: # Copyright (c) 2001-2010 Twisted Matrix Laboratories. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """Display a subunit stream through a colorized unittest test runner.""" import heapq import subunit import sys import unittest import six import testtools class _AnsiColorizer(object): """Colorizer allows callers to write text in a particular color. A colorizer is an object that loosely wraps around a stream, allowing callers to write text to the stream in a particular color. Colorizer classes must implement C{supported()} and C{write(text, color)}. """ _colors = dict(black=30, red=31, green=32, yellow=33, blue=34, magenta=35, cyan=36, white=37) def __init__(self, stream): self.stream = stream def supported(cls, stream=sys.stdout): """Check is the current platform supports coloring terminal output. A class method that returns True if the current platform supports coloring terminal output using this method. Returns False otherwise. """ if not stream.isatty(): return False # auto color only on TTYs try: import curses except ImportError: return False else: try: try: return curses.tigetnum("colors") > 2 except curses.error: curses.setupterm() return curses.tigetnum("colors") > 2 except Exception: # guess false in case of error return False supported = classmethod(supported) def write(self, text, color): """Write the given text to the stream in the given color. @param text: Text to be written to the stream. @param color: A string label for a color. e.g. 'red', 'white'. """ color = self._colors[color] self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text)) class _Win32Colorizer(object): """See _AnsiColorizer docstring.""" def __init__(self, stream): import win32console red, green, blue, bold = (win32console.FOREGROUND_RED, win32console.FOREGROUND_GREEN, win32console.FOREGROUND_BLUE, win32console.FOREGROUND_INTENSITY) self.stream = stream self.screenBuffer = win32console.GetStdHandle( win32console.STD_OUT_HANDLE) self._colors = { 'normal': red | green | blue, 'red': red | bold, 'green': green | bold, 'blue': blue | bold, 'yellow': red | green | bold, 'magenta': red | blue | bold, 'cyan': green | blue | bold, 'white': red | green | blue | bold, } def supported(cls, stream=sys.stdout): try: import win32console screenBuffer = win32console.GetStdHandle( win32console.STD_OUT_HANDLE) except ImportError: return False import pywintypes try: screenBuffer.SetConsoleTextAttribute( win32console.FOREGROUND_RED | win32console.FOREGROUND_GREEN | win32console.FOREGROUND_BLUE) except pywintypes.error: return False else: return True supported = classmethod(supported) def write(self, text, color): color = self._colors[color] self.screenBuffer.SetConsoleTextAttribute(color) self.stream.write(text) self.screenBuffer.SetConsoleTextAttribute(self._colors['normal']) class _NullColorizer(object): """See _AnsiColorizer docstring.""" def __init__(self, stream): self.stream = stream def supported(cls, stream=sys.stdout): return True supported = classmethod(supported) def write(self, text, color): self.stream.write(text) def get_elapsed_time_color(elapsed_time): if elapsed_time > 1.0: return 'red' elif elapsed_time > 0.25: return 'yellow' else: return 'green' class OpenStackTestResult(testtools.TestResult): def __init__(self, stream, descriptions, verbosity): super(OpenStackTestResult, self).__init__() self.stream = stream self.showAll = verbosity > 1 self.num_slow_tests = 10 self.slow_tests = [] # this is a fixed-sized heap self.colorizer = None # NOTE(vish): reset stdout for the terminal check stdout = sys.stdout sys.stdout = sys.__stdout__ for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: if colorizer.supported(): self.colorizer = colorizer(self.stream) break sys.stdout = stdout self.start_time = None self.last_time = {} self.results = {} self.last_written = None def _writeElapsedTime(self, elapsed): color = get_elapsed_time_color(elapsed) self.colorizer.write(" %.2f" % elapsed, color) def _addResult(self, test, *args): try: name = test.id() except AttributeError: name = 'Unknown.unknown' test_class, test_name = name.rsplit('.', 1) elapsed = (self._now() - self.start_time).total_seconds() item = (elapsed, test_class, test_name) if len(self.slow_tests) >= self.num_slow_tests: heapq.heappushpop(self.slow_tests, item) else: heapq.heappush(self.slow_tests, item) self.results.setdefault(test_class, []) self.results[test_class].append((test_name, elapsed) + args) self.last_time[test_class] = self._now() self.writeTests() def _writeResult(self, test_name, elapsed, long_result, color, short_result, success): if self.showAll: self.stream.write(' %s' % str(test_name).ljust(66)) self.colorizer.write(long_result, color) if success: self._writeElapsedTime(elapsed) self.stream.writeln() else: self.colorizer.write(short_result, color) def addSuccess(self, test): super(OpenStackTestResult, self).addSuccess(test) self._addResult(test, 'OK', 'green', '.', True) def addFailure(self, test, err): if test.id() == 'process-returncode': return super(OpenStackTestResult, self).addFailure(test, err) self._addResult(test, 'FAIL', 'red', 'F', False) def addError(self, test, err): super(OpenStackTestResult, self).addFailure(test, err) self._addResult(test, 'ERROR', 'red', 'E', False) def addSkip(self, test, reason=None, details=None): super(OpenStackTestResult, self).addSkip(test, reason, details) self._addResult(test, 'SKIP', 'blue', 'S', True) def startTest(self, test): self.start_time = self._now() super(OpenStackTestResult, self).startTest(test) def writeTestCase(self, cls): if not self.results.get(cls): return if cls != self.last_written: self.colorizer.write(cls, 'white') self.stream.writeln() for result in self.results[cls]: self._writeResult(*result) del self.results[cls] self.stream.flush() self.last_written = cls def writeTests(self): time = self.last_time.get(self.last_written, self._now()) if not self.last_written or (self._now() - time).total_seconds() > 2.0: diff = 3.0 while diff > 2.0: classes = self.results.keys() oldest = min(classes, key=lambda x: self.last_time[x]) diff = (self._now() - self.last_time[oldest]).total_seconds() self.writeTestCase(oldest) else: self.writeTestCase(self.last_written) def done(self): self.stopTestRun() def stopTestRun(self): for cls in list(six.iterkeys(self.results)): self.writeTestCase(cls) self.stream.writeln() self.writeSlowTests() def writeSlowTests(self): # Pare out 'fast' tests slow_tests = [item for item in self.slow_tests if get_elapsed_time_color(item[0]) != 'green'] if slow_tests: slow_total_time = sum(item[0] for item in slow_tests) slow = ("Slowest %i tests took %.2f secs:" % (len(slow_tests), slow_total_time)) self.colorizer.write(slow, 'yellow') self.stream.writeln() last_cls = None # sort by name for elapsed, cls, name in sorted(slow_tests, key=lambda x: x[1] + x[2]): if cls != last_cls: self.colorizer.write(cls, 'white') self.stream.writeln() last_cls = cls self.stream.write(' %s' % str(name).ljust(68)) self._writeElapsedTime(elapsed) self.stream.writeln() def printErrors(self): if self.showAll: self.stream.writeln() self.printErrorList('ERROR', self.errors) self.printErrorList('FAIL', self.failures) def printErrorList(self, flavor, errors): for test, err in errors: self.colorizer.write("=" * 70, 'red') self.stream.writeln() self.colorizer.write(flavor, 'red') self.stream.writeln(": %s" % test.id()) self.colorizer.write("-" * 70, 'red') self.stream.writeln() self.stream.writeln("%s" % err) test = subunit.ProtocolTestCase(sys.stdin, passthrough=None) if sys.version_info[0:2] <= (2, 6): runner = unittest.TextTestRunner(verbosity=2) else: runner = unittest.TextTestRunner(verbosity=2, resultclass=OpenStackTestResult) if runner.run(test).wasSuccessful(): exit_code = 0 else: exit_code = 1 sys.exit(exit_code) keystone-2014.1/tools/install_venv_common.py0000664000175400017540000001350612323716267022404 0ustar jenkinsjenkins00000000000000# Copyright 2013 OpenStack Foundation # Copyright 2013 IBM Corp. # # 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. """Provides methods needed by installation script for OpenStack development virtual environments. Since this script is used to bootstrap a virtualenv from the system's Python environment, it should be kept strictly compatible with Python 2.6. Synced in from openstack-common """ from __future__ import print_function import optparse import os import subprocess import sys class InstallVenv(object): def __init__(self, root, venv, requirements, test_requirements, py_version, project): self.root = root self.venv = venv self.requirements = requirements self.test_requirements = test_requirements self.py_version = py_version self.project = project def die(self, message, *args): print(message % args, file=sys.stderr) sys.exit(1) def check_python_version(self): if sys.version_info < (2, 6): self.die("Need Python Version >= 2.6") def run_command_with_code(self, cmd, redirect_output=True, check_exit_code=True): """Runs a command in an out-of-process shell. Returns the output of that command. Working directory is self.root. """ if redirect_output: stdout = subprocess.PIPE else: stdout = None proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout) output = proc.communicate()[0] if check_exit_code and proc.returncode != 0: self.die('Command "%s" failed.\n%s', ' '.join(cmd), output) return (output, proc.returncode) def run_command(self, cmd, redirect_output=True, check_exit_code=True): return self.run_command_with_code(cmd, redirect_output, check_exit_code)[0] def get_distro(self): if (os.path.exists('/etc/fedora-release') or os.path.exists('/etc/redhat-release')): return Fedora( self.root, self.venv, self.requirements, self.test_requirements, self.py_version, self.project) else: return Distro( self.root, self.venv, self.requirements, self.test_requirements, self.py_version, self.project) def check_dependencies(self): self.get_distro().install_virtualenv() def create_virtualenv(self, no_site_packages=True): """Creates the virtual environment and installs PIP. Creates the virtual environment and installs PIP only into the virtual environment. """ if not os.path.isdir(self.venv): print('Creating venv...', end=' ') if no_site_packages: self.run_command(['virtualenv', '-q', '--no-site-packages', self.venv]) else: self.run_command(['virtualenv', '-q', self.venv]) print('done.') else: print("venv already exists...") pass def pip_install(self, *args): self.run_command(['tools/with_venv.sh', 'pip', 'install', '--upgrade'] + list(args), redirect_output=False) def install_dependencies(self): print('Installing dependencies with pip (this can take a while)...') # First things first, make sure our venv has the latest pip and # setuptools and pbr self.pip_install('pip>=1.4') self.pip_install('setuptools') self.pip_install('pbr') self.pip_install('-r', self.requirements, '-r', self.test_requirements) def parse_args(self, argv): """Parses command-line arguments.""" parser = optparse.OptionParser() parser.add_option('-n', '--no-site-packages', action='store_true', help="Do not inherit packages from global Python " "install") return parser.parse_args(argv[1:])[0] class Distro(InstallVenv): def check_cmd(self, cmd): return bool(self.run_command(['which', cmd], check_exit_code=False).strip()) def install_virtualenv(self): if self.check_cmd('virtualenv'): return if self.check_cmd('easy_install'): print('Installing virtualenv via easy_install...', end=' ') if self.run_command(['easy_install', 'virtualenv']): print('Succeeded') return else: print('Failed') self.die('ERROR: virtualenv not found.\n\n%s development' ' requires virtualenv, please install it using your' ' favorite package management tool' % self.project) class Fedora(Distro): """This covers all Fedora-based distributions. Includes: Fedora, RHEL, CentOS, Scientific Linux """ def check_pkg(self, pkg): return self.run_command_with_code(['rpm', '-q', pkg], check_exit_code=False)[1] == 0 def install_virtualenv(self): if self.check_cmd('virtualenv'): return if not self.check_pkg('python-virtualenv'): self.die("Please install 'python-virtualenv'.") super(Fedora, self).install_virtualenv() keystone-2014.1/tools/debug_helper.sh0000775000175400017540000000060612323716267020737 0ustar jenkinsjenkins00000000000000#!/bin/bash TMP_DIR=`mktemp -d` || exit 1 trap "rm -rf $TMP_DIR" EXIT ALL_TESTS=$TMP_DIR/all_tests TESTS_TO_RUN=$TMP_DIR/ks_to_run python -m testtools.run discover -t ./ ./keystone/tests --list > $ALL_TESTS if [ "$1" ] then grep "$1" < $ALL_TESTS > $TESTS_TO_RUN else mv $ALL_TESTS $TESTS_TO_RUN fi STANDARD_THREADS=1 python -m testtools.run discover --load-list $TESTS_TO_RUN keystone-2014.1/examples/0000775000175400017540000000000012323716511016417 5ustar jenkinsjenkins00000000000000keystone-2014.1/examples/pki/0000775000175400017540000000000012323716511017202 5ustar jenkinsjenkins00000000000000keystone-2014.1/examples/pki/certs/0000775000175400017540000000000012323716511020322 5ustar jenkinsjenkins00000000000000keystone-2014.1/examples/pki/certs/signing_cert.pem0000664000175400017540000000245612323716267023517 0ustar jenkinsjenkins00000000000000-----BEGIN CERTIFICATE----- MIIDpTCCAo0CAREwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x MzA3MDkxNjI1MDBaGA8yMDcyMDEwMTE2MjUwMFowgY8xCzAJBgNVBAYTAlVTMQsw CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv cGVuc3RhY2sub3JnMREwDwYDVQQDEwhLZXlzdG9uZTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAMTC6IdNd9Cg1DshcrT5gRVRF36nEmjSA9QWdik7B925 PK70U4F6j4pz/5JL7plIo/8rJ4jJz9ccE7m0iA+IuABtEhEwXkG9rj47Oy0J4ZyD GSh2K1Bl78PA9zxXSzysUTSjBKdAh29dPYbJY7cgZJ0uC3AtfVceYiAOIi14SdFe Z0LZLDXBuLaqUmSMrmKwJ9wAMOCb/jbBP9/3Ycd0GYjlvrSBU4Bqb8/NHasyO4Dp PN68OAoyD5r5jUtV8QZN03UjIsoux8e0lrL6+MVtJo0OfWvlSrlzS5HKSryY+uqq QEuxtZKpJM2MV85ujvjc8eDSChh2shhDjBem3FIlHKUCAwEAATANBgkqhkiG9w0B AQUFAAOCAQEAed9fHgdJrk+gZcO5gsqq6uURfDOuYD66GsSdZw4BqHjYAcnyWq2d a+iw7Uxkqu7iLf2k4+Hu3xjDFrce479OwZkSnbXmqB7XspTGOuM8MgT7jB/ypKTO Z6qaZKSWK1Hta995hMrVVlhUNBLh0MPGqoVWYA4d7mblujgH9vp+4mpCciJagHks 8K5FBmI+pobB+uFdSYDoRzX9LTpStspK4e3IoY8baILuGcdKimRNBv6ItG4hMrnt Ae1/nWMJyUu5rDTGf2V/vAaS0S/faJBwQSz1o38QHMTWHNspfwIdX3yMqI9u7/vY lz3rLy5WdBdUgZrZ3/VLmJTiJVZu5Owq4Q== -----END CERTIFICATE----- keystone-2014.1/examples/pki/certs/cacert.pem0000664000175400017540000000255712323716267022307 0ustar jenkinsjenkins00000000000000-----BEGIN CERTIFICATE----- MIID1jCCAr6gAwIBAgIJAKiIU3dYUGKeMA0GCSqGSIb3DQEBBQUAMIGeMQowCAYD VQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55 dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMG CSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2Vs ZiBTaWduZWQwIBcNMTMwNzA5MTYyNTAwWhgPMjA3MjAxMDExNjI1MDBaMIGeMQow CAYDVQQFEwE1MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1 bm55dmFsZTESMBAGA1UEChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTEl MCMGCSqGSIb3DQEJARYWa2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxML U2VsZiBTaWduZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCh1U+N 3g2cjFi7GeVf21FIv8MDhughFCey9rysAuqFONSFYo2rectLgpDtVy4BFFUFlxmh 8Ci9TEZ5LiA31tbc4584GxvlLt4dg8aFsUJRBKq0L9i7W5v9uFpHrY1Zr+P4vwG+ v7IWOuzw19f517eGpp6LLcj2vrpN9Yb63rrydKOqr0KJodMd+vFKmi+euFcPqs6s w1OiC5DpJN479CGl2Fs1WzMoKDedRNiXG7ysrVrYQIkfMBABBPIwilq1xXZz9Ybo 0PbNgOu6xpSsy9hq+IzxcwYsr5CwIcbqW6Ju+Ti2iBEaff20lW7dFzO4kwrcqOr9 Jnn7qE8YfJo9Hyj3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN AQEFBQADggEBAGWFTQTe2FwvwGWa/Bx3Ypc8pJ05ucmGDm8XZiUHj1mOvFHTcveL Iofb+vR2lynr+MwF9Dn1szGteVNn/QxrHJIoxsgf1n/9fdyYqjoKWXblNBMt5jhr IlMGdQMqHSDzlkZKbcXg5vzHnG5mrwh0rojcZItZznXTSo/XnujEtHwIvCo6rk9c tRRzpkcDkg+/SZf2izchsLoEQVsJsIZMnWl0hUGFHaDfx2JQn7bnAcC84wPVhRJ+ Xa3kDok1r7Nd7Vr/Wf0hCNRxyv2dySD/bq5iCEl1HNik3KCq4eUicTtkGe5N+Was ucf1RhPD3oZbxlTX4QDN7grSCdrTESyuhfc= -----END CERTIFICATE----- keystone-2014.1/examples/pki/certs/middleware.pem0000664000175400017540000000572612323716267023164 0ustar jenkinsjenkins00000000000000-----BEGIN CERTIFICATE----- MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x MzA3MDkxNjI1MDBaGA8yMDcyMDEwMTE2MjUwMFowgZAxCzAJBgNVBAYTAlVTMQsw CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQC5dpW18l3bs+Mcj/JdhaAa+qw1RJwShm06g+q38ZoC cCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4GSI1pZa3iqbT9Yj70nxN+0l94iym+ v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6BdmwS0FuOy2qfKPnPhyBDH2VawtOgY MLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69KBJQElFXPQ9Nu0ABCPWWC2tN87L5 pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQuRnkMvQ/g887Sp6nEJ22ABPEFhuRr 89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cTnV9Dv6bfAgMBAAEwDQYJKoZIhvcN AQEFBQADggEBAIVz3ZwxSUF/y5ABmjnVIQaVVxH97bu07smFQUe0AB2I9R4xnBJ9 jn93DpeixZvArCZuDuJEJvNER8S6L3r/OPMPrVzayxibXATaZRE8khMWEJpsnyeW 8paA5NuZJwN2NjlPOmT47J1m7ZjLgkrVwjhwQZPMnh5kG9690TBJNhg9x3Z8f6p3 iKj2AfZWGhp9Xr2xOZCpfvAZmyvKOMeuHVrRZ2VWGuzojQd7fjSEDw/+Tg8Gw1LV BQXjXiKQHsD1YID2a9Pe9yrBjO00ZMxMw8+wN9qrh+8vxfmwTO8tEkmcpvM4ivO3 /oGGhQh6nSncERVI7rx+wBDnIHKBz6MU2Ow= -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5dpW18l3bs+Mc j/JdhaAa+qw1RJwShm06g+q38ZoCcCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4G SI1pZa3iqbT9Yj70nxN+0l94iym+v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6Bd mwS0FuOy2qfKPnPhyBDH2VawtOgYMLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69 KBJQElFXPQ9Nu0ABCPWWC2tN87L5pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQu RnkMvQ/g887Sp6nEJ22ABPEFhuRr89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cT nV9Dv6bfAgMBAAECggEBAIB1K5L/kZUITulMptGyKUgmkjq/D98g7u0Vy/CmTkcc Cx6F+LGsL9D8mfplDBKOpo4S530sfKk1+Uwu2ovDGqKhazQJ5ZMnz6gK7Ieg1ERD wDDURTIeyKf0HtJMGD0av2QU+GIeYXQEO446PhLCu+n42zkQ8tDS8xSJbCsu0odV ok6+i7nEg9sP4uDfAAtM8CUJbRpFTha+m2a7pOz3ylU7/ZV4FDIgJ+FEynaphXAo bZE4MX5I7A4DDBp7/9g9HsgefByY4xiABuk7Rsyztyf2TrJEtcsVhiV4sCIIHsow u60KGEcTQWj4npBIMgW1QUdrwmAAh/35gOjt9ZndgTkCgYEA2yT5DmihjVaNF65B 8VtdFcpESr8rr6FBmJ7z31m7MufeV1Inc5GqCK9agRmpr5sTYcgFB9it2IhW2WsA xHv+7J04bd9DBtgTv58GWrISsCR/abMZnJrm+F5Rafk77jwjCx/SwFj79ybI83Ia VJYMd7jqkxc00+DZT/3QWZqRrlsCgYEA2KeBBqUVdCpwNiJpgFM18HWjJx36HRk7 YoFapXot/6R6A/rYmS+/goBZt2CWqqGtnXqWEZvH+v4L+WlUmYQrWwtoxpdR1oXz EmlCxN7D9MbRVR7QVW24h5zdwPOlbCTGoKzowOs8UEjMfQ81zoMinLmcJgHQSyzs OawgSF+DmM0CgYBQz26EELNaMktvKxQoE3/c9CyAv8Q1TKqqxBq8BxPP7s7/tkzU AigIcdlW+Aapue7IxQCN5yocShJ0tE+hJPRZfpR7d7P4xx9pLxQhx766c4sEiEXu iPSZK/artHuUG1r01DRcN7QabJP3qeDpxjcswuTFfu49H5IjPD5jfGsyNwKBgFjh bvdQ5lo/xsUOnQV+HZTGTeaQT7l8TnZ85rkYRKKp0TysvgsqIYDiMuwd/fGGXnlK fyI+LG51pmftpD1OkZLKPXOrRHGjhjK5aCDn2rAimGI5P/KsDpXj7r1ntyeEdtAX 32y1lIrDMtDjWomcFqkBJGQbPl540Xhfeub1+EDJAoGAUZGPT2itKnxEFsa1SKHW yLeEsag/a9imAVyizo1WJn2WJaUhi1aHK49w6JRowIAzXXb7zLQt7BL8v+ydPVw3 eySpXGqFuN/Prm3So0SeWllWcPsKFAzjgE0CWjNuB0GlAZGOaJOcWUNoOZjX/SDC FpolIoaSad28tGc8tbEk3fU= -----END PRIVATE KEY----- keystone-2014.1/examples/pki/certs/ssl_cert.pem0000664000175400017540000000245612323716267022662 0ustar jenkinsjenkins00000000000000-----BEGIN CERTIFICATE----- MIIDpjCCAo4CARAwDQYJKoZIhvcNAQEFBQAwgZ4xCjAIBgNVBAUTATUxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQK EwlPcGVuU3RhY2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZr ZXlzdG9uZUBvcGVuc3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZDAgFw0x MzA3MDkxNjI1MDBaGA8yMDcyMDEwMTE2MjUwMFowgZAxCzAJBgNVBAYTAlVTMQsw CQYDVQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3Rh Y2sxETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBv cGVuc3RhY2sub3JnMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQC5dpW18l3bs+Mcj/JdhaAa+qw1RJwShm06g+q38ZoC cCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4GSI1pZa3iqbT9Yj70nxN+0l94iym+ v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6BdmwS0FuOy2qfKPnPhyBDH2VawtOgY MLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69KBJQElFXPQ9Nu0ABCPWWC2tN87L5 pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQuRnkMvQ/g887Sp6nEJ22ABPEFhuRr 89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cTnV9Dv6bfAgMBAAEwDQYJKoZIhvcN AQEFBQADggEBAIVz3ZwxSUF/y5ABmjnVIQaVVxH97bu07smFQUe0AB2I9R4xnBJ9 jn93DpeixZvArCZuDuJEJvNER8S6L3r/OPMPrVzayxibXATaZRE8khMWEJpsnyeW 8paA5NuZJwN2NjlPOmT47J1m7ZjLgkrVwjhwQZPMnh5kG9690TBJNhg9x3Z8f6p3 iKj2AfZWGhp9Xr2xOZCpfvAZmyvKOMeuHVrRZ2VWGuzojQd7fjSEDw/+Tg8Gw1LV BQXjXiKQHsD1YID2a9Pe9yrBjO00ZMxMw8+wN9qrh+8vxfmwTO8tEkmcpvM4ivO3 /oGGhQh6nSncERVI7rx+wBDnIHKBz6MU2Ow= -----END CERTIFICATE----- keystone-2014.1/examples/pki/cms/0000775000175400017540000000000012323716511017764 5ustar jenkinsjenkins00000000000000keystone-2014.1/examples/pki/cms/auth_token_revoked.json0000664000175400017540000000272012323716267024550 0ustar jenkinsjenkins00000000000000{"access": {"serviceCatalog": [{"endpoints": [{"adminURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", "region": "RegionOne", "internalURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", "publicURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a"}], "endpoints_links": [], "type": "volume", "name": "volume"}, {"endpoints": [{"adminURL": "http://127.0.0.1:9292/v1", "region": "RegionOne", "internalURL": "http://127.0.0.1:9292/v1", "publicURL": "http://127.0.0.1:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}, {"endpoints": [{"adminURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", "region": "RegionOne", "internalURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", "publicURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a"}], "endpoints_links": [], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL": "http://127.0.0.1:35357/v2.0", "region": "RegionOne", "internalURL": "http://127.0.0.1:35357/v2.0", "publicURL": "http://127.0.0.1:5000/v2.0"}], "endpoints_links": [], "type": "identity", "name": "keystone"}],"token": {"expires": "2012-06-02T14:47:34Z", "id": "placeholder", "tenant": {"enabled": true, "description": null, "name": "tenant_name1", "id": "tenant_id1"}}, "user": {"username": "revoked_username1", "roles_links": ["role1","role2"], "id": "revoked_user_id1", "roles": [{"name": "role1"}, {"name": "role2"}], "name": "revoked_username1"}}} keystone-2014.1/examples/pki/cms/revocation_list.pem0000664000175400017540000000153312323716267023705 0ustar jenkinsjenkins00000000000000-----BEGIN CMS----- MIICWgYJKoZIhvcNAQcCoIICSzCCAkcCAQExCTAHBgUrDgMCGjBpBgkqhkiG9w0B BwGgXARaeyJyZXZva2VkIjpbeyJpZCI6IjdhY2ZjZmRhZjZhMTRhZWJlOTdjNjFj NTk0N2JjNGQzIiwiZXhwaXJlcyI6IjIwMTItMDgtMTRUMTc6NTg6NDhaIn1dfQ0K MYIByjCCAcYCAQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYD VQQIEwJDQTESMBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3RhY2sx ETAPBgNVBAsTCEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVu c3RhY2sub3JnMRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjANBgkq hkiG9w0BAQEFAASCAQC2f05VHM7zjNT3TBO80AmZ00n7AEWUjbFe5nqIM8kWGM83 01Bi3uU/nQ0daAd3tqCmDL2EfETAjD+xnIzjlN6eIA74Vy51wFD/KiyWYPWzw8mH WcATHmE4E8kLdt8NhUodCY9TCFxcHJNDR1Eai/U7hH+5O4p9HcmMjv/GWegZL6HB Up9Cxu6haxvPFmYylzM6Qt0Ad/WiO/JZLPTA4qXJEJSa9EMFMb0c2wSDSn30swJe 7J79VTFktTr2djv8KFvaHr4vLFYv2Y3ZkTeHqam0m91vllxLZJUP5QTSHjjY6LFE 5eEjIlOv9wOOm1uTtPIq6pxCugU1Wm7gstkqr55R -----END CMS----- keystone-2014.1/examples/pki/cms/revocation_list.json0000664000175400017540000000013112323716267024066 0ustar jenkinsjenkins00000000000000{"revoked":[{"id":"7acfcfdaf6a14aebe97c61c5947bc4d3","expires":"2012-08-14T17:58:48Z"}]} keystone-2014.1/examples/pki/cms/auth_token_scoped.pem0000664000175400017540000000525412323716267024203 0ustar jenkinsjenkins00000000000000-----BEGIN CMS----- MIIHwQYJKoZIhvcNAQcCoIIHsjCCB64CAQExCTAHBgUrDgMCGjCCBc4GCSqGSIb3 DQEHAaCCBb8EggW7eyJhY2Nlc3MiOiB7InNlcnZpY2VDYXRhbG9nIjogW3siZW5k cG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3Yx LzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInJlZ2lvbiI6ICJy ZWdpb25PbmUiLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2 L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInB1YmxpY1VS TCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThh NjBmY2Y4OWJiNjYxN2EifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUi OiAidm9sdW1lIiwgIm5hbWUiOiAidm9sdW1lIn0sIHsiZW5kcG9pbnRzIjogW3si YWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwgInJlZ2lvbiI6 ICJyZWdpb25PbmUiLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5 MjkyL3YxIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjkyOTIvdjEi fV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiaW1hZ2UiLCAibmFt ZSI6ICJnbGFuY2UifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRw Oi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5 YmI2NjE3YSIsICJyZWdpb24iOiAicmVnaW9uT25lIiwgImludGVybmFsVVJMIjog Imh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYw ZmNmODliYjY2MTdhIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3 NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSJ9XSwgImVu ZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAi bm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xMjcu MC4wLjE6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAiUmVnaW9uT25lIiwgImludGVy bmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIuMCIsICJwdWJsaWNV UkwiOiAiaHR0cDovLzEyNy4wLjAuMTo1MDAwL3YyLjAifV0sICJlbmRwb2ludHNf bGlua3MiOiBbXSwgInR5cGUiOiAiaWRlbnRpdHkiLCAibmFtZSI6ICJrZXlzdG9u ZSJ9XSwidG9rZW4iOiB7ImV4cGlyZXMiOiAiMjAxMi0wNi0wMlQxNDo0NzozNFoi LCAiaWQiOiAicGxhY2Vob2xkZXIiLCAidGVuYW50IjogeyJlbmFibGVkIjogdHJ1 ZSwgImRlc2NyaXB0aW9uIjogbnVsbCwgIm5hbWUiOiAidGVuYW50X25hbWUxIiwg ImlkIjogInRlbmFudF9pZDEifX0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJ1c2Vy X25hbWUxIiwgInJvbGVzX2xpbmtzIjogWyJyb2xlMSIsInJvbGUyIl0sICJpZCI6 ICJ1c2VyX2lkMSIsICJyb2xlcyI6IFt7Im5hbWUiOiAicm9sZTEifSwgeyJuYW1l IjogInJvbGUyIn1dLCAibmFtZSI6ICJ1c2VyX25hbWUxIn19fQ0KMYIByjCCAcYC AQEwgaQwgZ4xCjAIBgNVBAUTATUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTES MBAGA1UEBxMJU3Vubnl2YWxlMRIwEAYDVQQKEwlPcGVuU3RhY2sxETAPBgNVBAsT CEtleXN0b25lMSUwIwYJKoZIhvcNAQkBFhZrZXlzdG9uZUBvcGVuc3RhY2sub3Jn MRQwEgYDVQQDEwtTZWxmIFNpZ25lZAIBETAHBgUrDgMCGjANBgkqhkiG9w0BAQEF AASCAQCAtuVtqTU9h1uaRrYU1eusSnHwD6jizp/xltTrYTyFPfYjhJdglS+bjSeS Iau9pN3Tfug98ozUTJ5ByNepAQtxBxPz5bDXhBmAbU6ywaolqRAG+b/s2ShNGQ2a tn80NeZmDNbtoqdHVAkD3EZXjsEKr2w+3JTTF2indzczyGe5EeSfNUaT+ZhNEmPR Urob62t8atW+zehCSurpaa8pC5m1NcbK8Uu6Y+qO2m08KU9w5kmbOQtWAGCmtpIx F2yM1AbSgd90yzen7dv5mNkgZyzQ6SYgRUvkKOKnCyBb97EZK3ZR4qUxQzRYM++8 g8HdaIfoYVPoPHqODet8Xmhw/Wtp -----END CMS----- keystone-2014.1/examples/pki/cms/auth_token_unscoped.pem0000664000175400017540000000216312323716267024542 0ustar jenkinsjenkins00000000000000-----BEGIN CMS----- MIIDKAYJKoZIhvcNAQcCoIIDGTCCAxUCAQExCTAHBgUrDgMCGjCCATUGCSqGSIb3 DQEHAaCCASYEggEieyJhY2Nlc3MiOiB7InRva2VuIjogeyJleHBpcmVzIjogIjIw MTItMDgtMTdUMTU6MzU6MzRaIiwgImlkIjogIjAxZTAzMmM5OTZlZjQ0MDZiMTQ0 MzM1OTE1YTQxZTc5In0sICJzZXJ2aWNlQ2F0YWxvZyI6IHt9LCAidXNlciI6IHsi dXNlcm5hbWUiOiAidXNlcl9uYW1lMSIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQi OiAiYzljODllM2JlM2VlNDUzZmJmMDBjNzk2NmY2ZDNmYmQiLCAicm9sZXMiOiBb eyduYW1lJzogJ3JvbGUxJ30seyduYW1lJzogJ3JvbGUyJ30sXSwgIm5hbWUiOiAi dXNlcl9uYW1lMSJ9fX0xggHKMIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkG A1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNV BAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEW FmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgER MAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAFyD9IH2bXsafCTyHEWS28zBuq03 ZNWXV4+0BfdMbX1ONkaQ7mLGRmfabLHwfE5RaSASFh/Doq7KTc8XrBVfTm9HQPGr TLZUawdYlyBFVq0PEE1cPvO9Blz4X/2Awcp/Q67YRd/oLCY2dFWMClMroXu1fy3P oFlpWPPhURrbU1GjhUgPIz0IxNGjfWEHVsb5kz7Bo4E8J3pgIkccm97XZZtiCwf7 DVNj+Eb5mRegGG6IgSSRpZULgnCmSofQ3RnW3jSCkDxLXDQm9IsaaLJsuUFLylGs mB/98w9mP192IGl5MVr8/tANXwb5ok2VatUp/Ww1U0IlWbhN374PbK76vcE= -----END CMS----- keystone-2014.1/examples/pki/cms/auth_token_revoked.pem0000664000175400017540000000531412323716267024362 0ustar jenkinsjenkins00000000000000-----BEGIN CMS----- MIIH1wYJKoZIhvcNAQcCoIIHyDCCB8QCAQExCTAHBgUrDgMCGjCCBeQGCSqGSIb3 DQEHAaCCBdUEggXReyJhY2Nlc3MiOiB7InNlcnZpY2VDYXRhbG9nIjogW3siZW5k cG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2L3Yx LzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInJlZ2lvbiI6ICJy ZWdpb25PbmUiLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc2 L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwgInB1YmxpY1VS TCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThh NjBmY2Y4OWJiNjYxN2EifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUi OiAidm9sdW1lIiwgIm5hbWUiOiAidm9sdW1lIn0sIHsiZW5kcG9pbnRzIjogW3si YWRtaW5VUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwgInJlZ2lvbiI6 ICJyZWdpb25PbmUiLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo5 MjkyL3YxIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjkyOTIvdjEi fV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiaW1hZ2UiLCAibmFt ZSI6ICJnbGFuY2UifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRw Oi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5 YmI2NjE3YSIsICJyZWdpb24iOiAicmVnaW9uT25lIiwgImludGVybmFsVVJMIjog Imh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYw ZmNmODliYjY2MTdhIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3 NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSJ9XSwgImVu ZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAi bm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xMjcu MC4wLjE6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAiUmVnaW9uT25lIiwgImludGVy bmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIuMCIsICJwdWJsaWNV UkwiOiAiaHR0cDovLzEyNy4wLjAuMTo1MDAwL3YyLjAifV0sICJlbmRwb2ludHNf bGlua3MiOiBbXSwgInR5cGUiOiAiaWRlbnRpdHkiLCAibmFtZSI6ICJrZXlzdG9u ZSJ9XSwidG9rZW4iOiB7ImV4cGlyZXMiOiAiMjAxMi0wNi0wMlQxNDo0NzozNFoi LCAiaWQiOiAicGxhY2Vob2xkZXIiLCAidGVuYW50IjogeyJlbmFibGVkIjogdHJ1 ZSwgImRlc2NyaXB0aW9uIjogbnVsbCwgIm5hbWUiOiAidGVuYW50X25hbWUxIiwg ImlkIjogInRlbmFudF9pZDEifX0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJyZXZv a2VkX3VzZXJuYW1lMSIsICJyb2xlc19saW5rcyI6IFsicm9sZTEiLCJyb2xlMiJd LCAiaWQiOiAicmV2b2tlZF91c2VyX2lkMSIsICJyb2xlcyI6IFt7Im5hbWUiOiAi cm9sZTEifSwgeyJuYW1lIjogInJvbGUyIn1dLCAibmFtZSI6ICJyZXZva2VkX3Vz ZXJuYW1lMSJ9fX0NCjGCAcowggHGAgEBMIGkMIGeMQowCAYDVQQFEwE1MQswCQYD VQQGEwJVUzELMAkGA1UECBMCQ0ExEjAQBgNVBAcTCVN1bm55dmFsZTESMBAGA1UE ChMJT3BlblN0YWNrMREwDwYDVQQLEwhLZXlzdG9uZTElMCMGCSqGSIb3DQEJARYW a2V5c3RvbmVAb3BlbnN0YWNrLm9yZzEUMBIGA1UEAxMLU2VsZiBTaWduZWQCAREw BwYFKw4DAhowDQYJKoZIhvcNAQEBBQAEggEAXY8JvllpyctcNlJByPLxhgLyRfFo Ew+8Yq3O4FxOyfVkINvOz4EHTipY0M/K8OLwfxpRt7o/iGLGRDBTI6Dd+erXsus8 NecnNxcWN9RUE2CZhoGj/0nhnNEGF+9Mlv3tMBngwoUJg2paSw/Vn2Q7RaqbOC05 aZOSDoSX7Zf0DIS/T0ZPnmOUb9+N25M20ctMHksPMEq0qyf2oove0O+WMa/cA8JT c2EAhew4WSD0Zv0GOAP30GS+hkNfA1GZTrvCQrpRs9jXhK4dR2bBsnUFVix1BEZ0 sDhI8cXLvm16IpOO8ov6002ZoZhPn6Qo+0J8QOfdnjiwNnxLOEbuOIwPeQ== -----END CMS----- keystone-2014.1/examples/pki/cms/auth_token_unscoped.json0000664000175400017540000000044212323716267024730 0ustar jenkinsjenkins00000000000000{"access": {"token": {"expires": "2012-08-17T15:35:34Z", "id": "01e032c996ef4406b144335915a41e79"}, "serviceCatalog": {}, "user": {"username": "user_name1", "roles_links": [], "id": "c9c89e3be3ee453fbf00c7966f6d3fbd", "roles": [{"name": "role1"},{"name": "role2"}], "name": "user_name1"}}} keystone-2014.1/examples/pki/cms/auth_token_scoped.json0000664000175400017540000000267212323716267024374 0ustar jenkinsjenkins00000000000000{"access": {"serviceCatalog": [{"endpoints": [{"adminURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", "region": "RegionOne", "internalURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", "publicURL": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a"}], "endpoints_links": [], "type": "volume", "name": "volume"}, {"endpoints": [{"adminURL": "http://127.0.0.1:9292/v1", "region": "RegionOne", "internalURL": "http://127.0.0.1:9292/v1", "publicURL": "http://127.0.0.1:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}, {"endpoints": [{"adminURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", "region": "RegionOne", "internalURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", "publicURL": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a"}], "endpoints_links": [], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL": "http://127.0.0.1:35357/v2.0", "region": "RegionOne", "internalURL": "http://127.0.0.1:35357/v2.0", "publicURL": "http://127.0.0.1:5000/v2.0"}], "endpoints_links": [], "type": "identity", "name": "keystone"}],"token": {"expires": "2012-06-02T14:47:34Z", "id": "placeholder", "tenant": {"enabled": true, "description": null, "name": "tenant_name1", "id": "tenant_id1"}}, "user": {"username": "user_name1", "roles_links": ["role1","role2"], "id": "user_id1", "roles": [{"name": "role1"}, {"name": "role2"}], "name": "user_name1"}}} keystone-2014.1/examples/pki/private/0000775000175400017540000000000012323716511020654 5ustar jenkinsjenkins00000000000000keystone-2014.1/examples/pki/private/ssl_key.pem0000664000175400017540000000325012323716267023040 0ustar jenkinsjenkins00000000000000-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5dpW18l3bs+Mc j/JdhaAa+qw1RJwShm06g+q38ZoCcCmRO3/XyHghgHWdVa+FKVm2ug923dE2PW4G SI1pZa3iqbT9Yj70nxN+0l94iym+v9/P7irolvo5OWBbBIJT1Ubjps5fJ//gz6Bd mwS0FuOy2qfKPnPhyBDH2VawtOgYMLk+PSG3YQh7vM2YvDALPTPz/f4qPmhQpb69 KBJQElFXPQ9Nu0ABCPWWC2tN87L5pakFw5zq46pttSJ7Izc8MXh3KQrh9FvjmiQu RnkMvQ/g887Sp6nEJ22ABPEFhuRr89aup6wRD2CkA/8L3zSB5BV7tTK4hQiq07cT nV9Dv6bfAgMBAAECggEBAIB1K5L/kZUITulMptGyKUgmkjq/D98g7u0Vy/CmTkcc Cx6F+LGsL9D8mfplDBKOpo4S530sfKk1+Uwu2ovDGqKhazQJ5ZMnz6gK7Ieg1ERD wDDURTIeyKf0HtJMGD0av2QU+GIeYXQEO446PhLCu+n42zkQ8tDS8xSJbCsu0odV ok6+i7nEg9sP4uDfAAtM8CUJbRpFTha+m2a7pOz3ylU7/ZV4FDIgJ+FEynaphXAo bZE4MX5I7A4DDBp7/9g9HsgefByY4xiABuk7Rsyztyf2TrJEtcsVhiV4sCIIHsow u60KGEcTQWj4npBIMgW1QUdrwmAAh/35gOjt9ZndgTkCgYEA2yT5DmihjVaNF65B 8VtdFcpESr8rr6FBmJ7z31m7MufeV1Inc5GqCK9agRmpr5sTYcgFB9it2IhW2WsA xHv+7J04bd9DBtgTv58GWrISsCR/abMZnJrm+F5Rafk77jwjCx/SwFj79ybI83Ia VJYMd7jqkxc00+DZT/3QWZqRrlsCgYEA2KeBBqUVdCpwNiJpgFM18HWjJx36HRk7 YoFapXot/6R6A/rYmS+/goBZt2CWqqGtnXqWEZvH+v4L+WlUmYQrWwtoxpdR1oXz EmlCxN7D9MbRVR7QVW24h5zdwPOlbCTGoKzowOs8UEjMfQ81zoMinLmcJgHQSyzs OawgSF+DmM0CgYBQz26EELNaMktvKxQoE3/c9CyAv8Q1TKqqxBq8BxPP7s7/tkzU AigIcdlW+Aapue7IxQCN5yocShJ0tE+hJPRZfpR7d7P4xx9pLxQhx766c4sEiEXu iPSZK/artHuUG1r01DRcN7QabJP3qeDpxjcswuTFfu49H5IjPD5jfGsyNwKBgFjh bvdQ5lo/xsUOnQV+HZTGTeaQT7l8TnZ85rkYRKKp0TysvgsqIYDiMuwd/fGGXnlK fyI+LG51pmftpD1OkZLKPXOrRHGjhjK5aCDn2rAimGI5P/KsDpXj7r1ntyeEdtAX 32y1lIrDMtDjWomcFqkBJGQbPl540Xhfeub1+EDJAoGAUZGPT2itKnxEFsa1SKHW yLeEsag/a9imAVyizo1WJn2WJaUhi1aHK49w6JRowIAzXXb7zLQt7BL8v+ydPVw3 eySpXGqFuN/Prm3So0SeWllWcPsKFAzjgE0CWjNuB0GlAZGOaJOcWUNoOZjX/SDC FpolIoaSad28tGc8tbEk3fU= -----END PRIVATE KEY----- keystone-2014.1/examples/pki/private/signing_key.pem0000664000175400017540000000325012323716267023675 0ustar jenkinsjenkins00000000000000-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEwuiHTXfQoNQ7 IXK0+YEVURd+pxJo0gPUFnYpOwfduTyu9FOBeo+Kc/+SS+6ZSKP/KyeIyc/XHBO5 tIgPiLgAbRIRMF5Bva4+OzstCeGcgxkoditQZe/DwPc8V0s8rFE0owSnQIdvXT2G yWO3IGSdLgtwLX1XHmIgDiIteEnRXmdC2Sw1wbi2qlJkjK5isCfcADDgm/42wT/f 92HHdBmI5b60gVOAam/PzR2rMjuA6TzevDgKMg+a+Y1LVfEGTdN1IyLKLsfHtJay +vjFbSaNDn1r5Uq5c0uRykq8mPrqqkBLsbWSqSTNjFfObo743PHg0goYdrIYQ4wX ptxSJRylAgMBAAECggEBAIDQPVz/CXarI+ZGQotaYPisqx3+kN3QyDLcNaVOgRrW P3UmfVjh/QEeae3ECkONu9e8z9gMjyX7uqo0F3NcBWI6Bb79FGgjnuQc8OPOeUZ2 yUyk+DxdT/eu5+04FQh2o387TjuU0lXFDBem1sI30cbZMyHQliMnwAPOXO+5tVH8 PusGNBMVvoCyfnj52uVjmAjPqLXyOMcKEhuJFbhnUURKvzkHRf43SWQsb081eh2m ACQ7uNzX7vg3aPXxSZXY2+hHX67POdqosjddu6CfoXcEHAOAUujvTOFvd1gGRkRo uOi5hNQqcN5uaqeq9enVThINDyFMzngZBhMCzRTWeK0CgYEA4qUhB7lJZLt9niDW 4Fudda1Pzu3XfxHsSG4D+xx5LunKb3ChG5x7PSLJvusfvnkm5fqhEEhbSVARo6Vn AAA52u5SPDDNwyk1ttvBR/Fc7eGwpbRQry2I6ui6baKiIOSV2K3vJlsSK8/GMQqu j0fstJuSvQR7Y6NUYxlWi+VNussCgYEA3j7tFAdGFc5JkeTHSzsU4h2+17uVDSSi yr7Duc9+9fwAbsO4go9x1CAOvV2r0WX10jPsTGg1d31pWLvJrS6QsAffmM+A0QIT eBX+umcavXWy69VExWa0xKU9wTE/nQvX9Fr8A+Klh/WfMcvoomK2zgOKoRSmes04 WKYlHWsSaE8CgYBUYcZ6abG5n1SVmwRlY7asKWqdUE/7L2EZVlyFEYTMwp5r/zL8 ZLY9fMZAHqoi8FhbJ4Tv2wChuv3WP66pgWwI5tIXNtRk5OLqwcakUmiW6IAsMYYY sotXam5+gx55wKFJmvh+/0k0ppbTi3aSQeUPGRz44sJNxnGUs8pVK3pVIQKBgQDD ga+lEtEAlbv6b7sx3wN79pbPyOBR84yRtkcPygzx74Gh7uL9V5rW9GyDAUgIqR0a kTqp7HI8b0KhIHFFu9TkRcjY8JFtS9o8pXy0FcdcK5H+DFq3HKag5ovwy5YeXTDY cMGJ2XOsqtIkSDCZySTvDgaBtVzOYoHS2jWEL5C92QKBgGmL2juXIB+HAi7UuKPg nWkVTikt5Zr2GNgYtso75E7+ljaRuf4D9eEBiOD1qYKQm8KvsiVzEs71BSmT1p1C b2hlM/5Crb7KumIkHTARQFr5NPwuBZ6NA6RLnd++vKi0WgOJtDAlR3bgwugfQdzZ 4Isaq9Rgfa/EHCKB2weQ7c3r -----END PRIVATE KEY----- keystone-2014.1/examples/pki/private/cakey.pem0000664000175400017540000000325012323716267022463 0ustar jenkinsjenkins00000000000000-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCh1U+N3g2cjFi7 GeVf21FIv8MDhughFCey9rysAuqFONSFYo2rectLgpDtVy4BFFUFlxmh8Ci9TEZ5 LiA31tbc4584GxvlLt4dg8aFsUJRBKq0L9i7W5v9uFpHrY1Zr+P4vwG+v7IWOuzw 19f517eGpp6LLcj2vrpN9Yb63rrydKOqr0KJodMd+vFKmi+euFcPqs6sw1OiC5Dp JN479CGl2Fs1WzMoKDedRNiXG7ysrVrYQIkfMBABBPIwilq1xXZz9Ybo0PbNgOu6 xpSsy9hq+IzxcwYsr5CwIcbqW6Ju+Ti2iBEaff20lW7dFzO4kwrcqOr9Jnn7qE8Y fJo9Hyj3AgMBAAECggEAPeEVaTaF190mNGyDczKmEv4X8CpOag+N2nVT0SXQTJ5d TJ9RckbAwB+tkMLr+Uev9tI+39e3jCI1NDK56QAB6jYy9D4RXYGdNoXji80qgVYa e4lsAr/Vlp8+DfhDew6xSbSnUytzSeLAJJsznvmn2Bmvt6ILHKXzEMoYEabGrtvk 0n31mmd6sszW6i1cYEhr3gK/VXaO4gM1oWit9aeIJDg3/D3UNUW7aoCTeCz91Gif 87/JH3UIPEIt960jb3oV7ltajRSpiSOfefJFwz/2n09+/P/Sg1+SWAraqkqaLqhO zoslYSYUuOQv+j97iD/tDVBjiWR1TrzQjf/3noOl+QKBgQDTExaIe0YYI8KdBNZ6 1cG3vztNWDh0PaP1n0n/bJYAGmAfxfn/gSrABXfeIAjy01f76EK2lPa/i8+DR7vL dJnUMO10OxaIZKr+OtR1XrMM6kREj6H5yHTNz0sJ3hDEfwJ1BndqwrXlCLAe7upe veXI9LVfPjPVmf8t9UwyxtaNiwKBgQDERzCGEuyKIeSfgytcdknJ0W+AbdkshC92 tZQPbI35YOLac2/y7GMjjf5Xg5VJRIYwXAG8ha+61Tvd7+qCVdzNyYfyOoBEE69B Gc9UdpXRfIjxokfidqh7mIIfjFNSI/UyVmvL9wrregXPcM+s7OlLC/0O82gOcNxU GKF3oP5XxQKBgQCPZEZIjcZ+m7yYQzMZ26FwnL9Cug4QGdgLAx2YIkJ8624l568A ftV2AcD+67Boll8NSSoZM3W1htuAifjwLNRcLKkD7yhNnGX1tC2lVqI4weWC1jjp od6H+q01lOC7PLWEntH9ey1q3M4ZFaGunz89l9CnVXCNScLri9sqG56iJQKBgHOc 50UiInhe7HbU4ZauClq5Za9FhRXGqtqGrDbFn38UBavdMUTq3p6Txgwwcp/coBoe J9uu90razU+2QPESuGPy4IPa17DB04pKNKiwzSC+9T83cpY/hJCAzazdkDqi+Yv0 Abz7wE/h6Ug+T+WxCt3sqtvCnjlbWzyh4YJAr3BtAoGBAIibPCEfVOwOfMOXkhIb liRVVGNxXQa6MwGVVfyR9gmlM85IjcBjh+Tf5+v3Mo286OlzLXQjfYW5pXR5Mgaw bKe+z5AqJlOsA+lJGTyCNnPKwaXAYHt8dZ41WhgzekibHCx7EQ+8jH1jkz2Gwou6 MDbnRu+e0FCyRFSuhB9Cim/K -----END PRIVATE KEY----- keystone-2014.1/examples/pki/gen_pki.sh0000775000175400017540000001340512323716267021170 0ustar jenkinsjenkins00000000000000#!/bin/bash # Copyright 2012 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. # This script generates the crypto necessary for the SSL tests. DIR=`dirname "$0"` CURRENT_DIR=`cd "$DIR" && pwd` CERTS_DIR=$CURRENT_DIR/certs PRIVATE_DIR=$CURRENT_DIR/private CMS_DIR=$CURRENT_DIR/cms function rm_old { rm -rf $CERTS_DIR/*.pem rm -rf $PRIVATE_DIR/*.pem } function cleanup { rm -rf *.conf > /dev/null 2>&1 rm -rf index* > /dev/null 2>&1 rm -rf *.crt > /dev/null 2>&1 rm -rf newcerts > /dev/null 2>&1 rm -rf *.pem > /dev/null 2>&1 rm -rf serial* > /dev/null 2>&1 } function generate_ca_conf { echo ' [ req ] default_bits = 2048 default_keyfile = cakey.pem default_md = default prompt = no distinguished_name = ca_distinguished_name x509_extensions = ca_extensions [ ca_distinguished_name ] serialNumber = 5 countryName = US stateOrProvinceName = CA localityName = Sunnyvale organizationName = OpenStack organizationalUnitName = Keystone emailAddress = keystone@openstack.org commonName = Self Signed [ ca_extensions ] basicConstraints = critical,CA:true ' > ca.conf } function generate_ssl_req_conf { echo ' [ req ] default_bits = 2048 default_keyfile = keystonekey.pem default_md = default prompt = no distinguished_name = distinguished_name [ distinguished_name ] countryName = US stateOrProvinceName = CA localityName = Sunnyvale organizationName = OpenStack organizationalUnitName = Keystone commonName = localhost emailAddress = keystone@openstack.org ' > ssl_req.conf } function generate_cms_signing_req_conf { echo ' [ req ] default_bits = 2048 default_keyfile = keystonekey.pem default_md = default prompt = no distinguished_name = distinguished_name [ distinguished_name ] countryName = US stateOrProvinceName = CA localityName = Sunnyvale organizationName = OpenStack organizationalUnitName = Keystone commonName = Keystone emailAddress = keystone@openstack.org ' > cms_signing_req.conf } function generate_signing_conf { echo ' [ ca ] default_ca = signing_ca [ signing_ca ] dir = . database = $dir/index.txt new_certs_dir = $dir/newcerts certificate = $dir/certs/cacert.pem serial = $dir/serial private_key = $dir/private/cakey.pem default_days = 21360 default_crl_days = 30 default_md = default policy = policy_any [ policy_any ] countryName = supplied stateOrProvinceName = supplied localityName = optional organizationName = supplied organizationalUnitName = supplied emailAddress = supplied commonName = supplied ' > signing.conf } function setup { touch index.txt echo '10' > serial generate_ca_conf mkdir newcerts } function check_error { if [ $1 != 0 ] ; then echo "Failed! rc=${1}" echo 'Bailing ...' cleanup exit $1 else echo 'Done' fi } function generate_ca { echo 'Generating New CA Certificate ...' openssl req -x509 -newkey rsa:2048 -days 21360 -out $CERTS_DIR/cacert.pem -keyout $PRIVATE_DIR/cakey.pem -outform PEM -config ca.conf -nodes check_error $? } function ssl_cert_req { echo 'Generating SSL Certificate Request ...' generate_ssl_req_conf openssl req -newkey rsa:2048 -keyout $PRIVATE_DIR/ssl_key.pem -keyform PEM -out ssl_req.pem -outform PEM -config ssl_req.conf -nodes check_error $? #openssl req -in req.pem -text -noout } function cms_signing_cert_req { echo 'Generating CMS Signing Certificate Request ...' generate_cms_signing_req_conf openssl req -newkey rsa:2048 -keyout $PRIVATE_DIR/signing_key.pem -keyform PEM -out cms_signing_req.pem -outform PEM -config cms_signing_req.conf -nodes check_error $? #openssl req -in req.pem -text -noout } function issue_certs { generate_signing_conf echo 'Issuing SSL Certificate ...' openssl ca -in ssl_req.pem -config signing.conf -batch check_error $? openssl x509 -in $CURRENT_DIR/newcerts/10.pem -out $CERTS_DIR/ssl_cert.pem check_error $? echo 'Issuing CMS Signing Certificate ...' openssl ca -in cms_signing_req.pem -config signing.conf -batch check_error $? openssl x509 -in $CURRENT_DIR/newcerts/11.pem -out $CERTS_DIR/signing_cert.pem check_error $? } function create_middleware_cert { cp $CERTS_DIR/ssl_cert.pem $CERTS_DIR/middleware.pem cat $PRIVATE_DIR/ssl_key.pem >> $CERTS_DIR/middleware.pem } function check_openssl { echo 'Checking openssl availability ...' which openssl check_error $? } function gen_sample_cms { for json_file in "${CMS_DIR}/auth_token_revoked.json" "${CMS_DIR}/auth_token_unscoped.json" "${CMS_DIR}/auth_token_scoped.json" "${CMS_DIR}/revocation_list.json" do openssl cms -sign -in $json_file -nosmimecap -signer $CERTS_DIR/signing_cert.pem -inkey $PRIVATE_DIR/signing_key.pem -outform PEM -nodetach -nocerts -noattr -out ${json_file/.json/.pem} done } check_openssl rm_old cleanup setup generate_ca ssl_cert_req cms_signing_cert_req issue_certs create_middleware_cert gen_sample_cms cleanup keystone-2014.1/README.rst0000664000175400017540000000257012323716267016304 0ustar jenkinsjenkins00000000000000================== OpenStack Keystone ================== Keystone provides authentication, authorization and service discovery mechanisms via HTTP primarily for use by projects in the OpenStack family. It is most commonly deployed as an HTTP interface to existing identity systems, such as LDAP. Developer documentation, the source of which is in ``doc/source/``, is published at: http://keystone.openstack.org/ The API specification is available at: https://github.com/openstack/identity-api The API documentation is available at: http://api.openstack.org/api-ref-identity.html The canonical client library is available at: https://github.com/openstack/python-keystoneclient Documentation for cloud administrators is available at: http://docs.openstack.org/ The source of documentation for cloud administrators is available at: https://github.com/openstack/openstack-manuals Information about our team meeting is available at: https://wiki.openstack.org/wiki/Meetings/KeystoneMeeting Bugs and feature requests are tracked on Launchpad at: https://bugs.launchpad.net/keystone Future design work is tracked at: https://blueprints.launchpad.net/keystone Contributors are encouraged to join IRC (``#openstack-keystone`` on freenode): https://wiki.openstack.org/wiki/IRC For information on contributing to Keystone, see ``CONTRIBUTING.rst``. keystone-2014.1/openstack-common.conf0000664000175400017540000000053612323716267020741 0ustar jenkinsjenkins00000000000000[DEFAULT] # The list of modules to copy from openstack-common module=db module=db.sqlalchemy module=config module=colorizer module=fixture module=importutils module=install_venv_common module=jsonutils module=log module=log_handler module=policy module=strutils module=timeutils # The base module to hold the copy of openstack.common base=keystone keystone-2014.1/PKG-INFO0000664000175400017540000000470312323716511015702 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: keystone Version: 2014.1 Summary: OpenStack Identity Home-page: http://www.openstack.org/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ================== OpenStack Keystone ================== Keystone provides authentication, authorization and service discovery mechanisms via HTTP primarily for use by projects in the OpenStack family. It is most commonly deployed as an HTTP interface to existing identity systems, such as LDAP. Developer documentation, the source of which is in ``doc/source/``, is published at: http://keystone.openstack.org/ The API specification is available at: https://github.com/openstack/identity-api The API documentation is available at: http://api.openstack.org/api-ref-identity.html The canonical client library is available at: https://github.com/openstack/python-keystoneclient Documentation for cloud administrators is available at: http://docs.openstack.org/ The source of documentation for cloud administrators is available at: https://github.com/openstack/openstack-manuals Information about our team meeting is available at: https://wiki.openstack.org/wiki/Meetings/KeystoneMeeting Bugs and feature requests are tracked on Launchpad at: https://bugs.launchpad.net/keystone Future design work is tracked at: https://blueprints.launchpad.net/keystone Contributors are encouraged to join IRC (``#openstack-keystone`` on freenode): https://wiki.openstack.org/wiki/IRC For information on contributing to Keystone, see ``CONTRIBUTING.rst``. Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 2.6 keystone-2014.1/.testr.conf0000664000175400017540000000116412323716272016675 0ustar jenkinsjenkins00000000000000[DEFAULT] test_command=${PYTHON:-python} -m subunit.run discover \ -t ./ ./keystone/tests \ $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list group_regex=.*(test_cert_setup|test_keystoneclient).+ # NOTE(morganfainberg): If single-worker mode is wanted (e.g. for live tests) # the environment variable ``TEST_RUN_CONCURRENCY`` should be set to ``1``. If # a non-default (1 worker per available core) concurrency is desired, set # environment variable ``TEST_RUN_CONCURRENCY`` to the desired number of # workers. test_run_concurrency=echo ${TEST_RUN_CONCURRENCY:-1} keystone-2014.1/bin/0000775000175400017540000000000012323716511015351 5ustar jenkinsjenkins00000000000000keystone-2014.1/bin/keystone-all0000775000175400017540000001146512323716267017725 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright 2013 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. import logging import os import signal import socket import sys # If ../keystone/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... possible_topdir = os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir, os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): sys.path.insert(0, possible_topdir) from paste import deploy import pbr.version from keystone.openstack.common import gettextutils # NOTE(dstanek): gettextutils.enable_lazy() must be called before # gettextutils._() is called to ensure it has the desired lazy lookup # behavior. This includes cases, like keystone.exceptions, where # gettextutils._() is called at import time. gettextutils.enable_lazy() from keystone.common import dependency from keystone.common import environment from keystone.common import sql from keystone.common import utils from keystone import config from keystone.openstack.common.gettextutils import _ from keystone.openstack.common import importutils from keystone import service CONF = config.CONF def create_server(conf, name, host, port): app = deploy.loadapp('config:%s' % conf, name=name) server = environment.Server(app, host=host, port=port, keepalive=CONF.tcp_keepalive, keepidle=CONF.tcp_keepidle) if CONF.ssl.enable: server.set_ssl(CONF.ssl.certfile, CONF.ssl.keyfile, CONF.ssl.ca_certs, CONF.ssl.cert_required) return name, server def sigint_handler(signal, frame): """Exits at SIGINT signal.""" logging.debug('SIGINT received, stopping servers.') sys.exit(0) def serve(*servers): signal.signal(signal.SIGINT, sigint_handler) for name, server in servers: try: server.start() except socket.error: logging.exception(_('Failed to start the %(name)s server') % { 'name': name}) raise # notify calling process we are ready to serve if CONF.onready: try: notifier = importutils.import_module(CONF.onready) notifier.notify() except ImportError: try: utils.check_output(CONF.onready.split()) except Exception: logging.exception('Failed to execute onready command') for name, server in servers: server.wait() if __name__ == '__main__': dev_conf = os.path.join(possible_topdir, 'etc', 'keystone.conf') config_files = None if os.path.exists(dev_conf): config_files = [dev_conf] config.configure() sql.initialize() config.set_default_for_default_log_levels() CONF(project='keystone', version=pbr.version.VersionInfo('keystone').version_string(), default_config_files=config_files) config.setup_logging() # Log the options used when starting if we're in debug mode... if CONF.debug: CONF.log_opt_values(logging.getLogger(CONF.prog), logging.DEBUG) paste_config = config.find_paste_config() monkeypatch_thread = not CONF.standard_threads pydev_debug_url = utils.setup_remote_pydev_debug() if pydev_debug_url: # in order to work around errors caused by monkey patching we have to # set the thread to False. An explanation is here: # http://lists.openstack.org/pipermail/openstack-dev/2012-August/ # 000794.html monkeypatch_thread = False environment.use_eventlet(monkeypatch_thread) service.load_backends() servers = [] servers.append(create_server(paste_config, 'admin', CONF.admin_bind_host, int(CONF.admin_port))) servers.append(create_server(paste_config, 'main', CONF.public_bind_host, int(CONF.public_port))) dependency.resolve_future_dependencies() serve(*servers) keystone-2014.1/bin/keystone-manage0000775000175400017540000000353412323716267020403 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright 2013 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. import os import sys # If ../keystone/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): sys.path.insert(0, possible_topdir) from keystone.openstack.common import gettextutils # NOTE(dstanek): gettextutils.enable_lazy() must be called before # gettextutils._() is called to ensure it has the desired lazy lookup # behavior. This includes cases, like keystone.exceptions, where # gettextutils._() is called at import time. gettextutils.enable_lazy() from keystone import cli from keystone.common import environment if __name__ == '__main__': environment.use_stdlib() dev_conf = os.path.join(possible_topdir, 'etc', 'keystone.conf') config_files = None if os.path.exists(dev_conf): config_files = [dev_conf] cli.main(argv=sys.argv, config_files=config_files) keystone-2014.1/etc/0000775000175400017540000000000012323716511015354 5ustar jenkinsjenkins00000000000000keystone-2014.1/etc/logging.conf.sample0000664000175400017540000000202612323716267021141 0ustar jenkinsjenkins00000000000000[loggers] keys=root,access [handlers] keys=production,file,access_file,devel [formatters] keys=minimal,normal,debug ########### # Loggers # ########### [logger_root] level=WARNING handlers=file [logger_access] level=INFO qualname=access handlers=access_file ################ # Log Handlers # ################ [handler_production] class=handlers.SysLogHandler level=ERROR formatter=normal args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER) [handler_file] class=handlers.WatchedFileHandler level=WARNING formatter=normal args=('error.log',) [handler_access_file] class=handlers.WatchedFileHandler level=INFO formatter=minimal args=('access.log',) [handler_devel] class=StreamHandler level=NOTSET formatter=debug args=(sys.stdout,) ################## # Log Formatters # ################## [formatter_minimal] format=%(message)s [formatter_normal] format=(%(name)s): %(asctime)s %(levelname)s %(message)s [formatter_debug] format=(%(name)s): %(asctime)s %(levelname)s %(module)s %(funcName)s %(message)s keystone-2014.1/etc/keystone.conf.sample0000664000175400017540000011302712323716272021354 0ustar jenkinsjenkins00000000000000[DEFAULT] # # Options defined in keystone # # A "shared secret" that can be used to bootstrap Keystone. # This "token" does not represent a user, and carries no # explicit authorization. To disable in production (highly # recommended), remove AdminTokenAuthMiddleware from your # paste application pipelines (for example, in keystone- # paste.ini). (string value) #admin_token=ADMIN # The IP Address of the network interface to for the public # service to listen on. (string value) # Deprecated group/name - [DEFAULT]/bind_host #public_bind_host=0.0.0.0 # The IP Address of the network interface to for the admin # service to listen on. (string value) # Deprecated group/name - [DEFAULT]/bind_host #admin_bind_host=0.0.0.0 # The port which the OpenStack Compute service listens on. # (integer value) #compute_port=8774 # The port number which the admin service listens on. (integer # value) #admin_port=35357 # The port number which the public service listens on. # (integer value) #public_port=5000 # The base public endpoint URL for keystone that are # advertised to clients (NOTE: this does NOT affect how # keystone listens for connections) (string value). # Defaults to the base host URL of the request. Eg a # request to http://server:5000/v2.0/users will # default to http://server:5000. You should only need # to set this value if the base URL contains a path # (eg /prefix/v2.0) or the endpoint should be found on # a different server. #public_endpoint=http://localhost:%(public_port)s/ # The base admin endpoint URL for keystone that are advertised # to clients (NOTE: this does NOT affect how keystone listens # for connections) (string value). # Defaults to the base host URL of the request. Eg a # request to http://server:35357/v2.0/users will # default to http://server:35357. You should only need # to set this value if the base URL contains a path # (eg /prefix/v2.0) or the endpoint should be found on # a different server. #admin_endpoint=http://localhost:%(admin_port)s/ # onready allows you to send a notification when the process # is ready to serve For example, to have it notify using # systemd, one could set shell command: "onready = systemd- # notify --ready" or a module with notify() method: "onready = # keystone.common.systemd". (string value) #onready= # enforced by optional sizelimit middleware # (keystone.middleware:RequestBodySizeLimiter). (integer # value) #max_request_body_size=114688 # limit the sizes of user & tenant ID/names. (integer value) #max_param_size=64 # similar to max_param_size, but provides an exception for # token values. (integer value) #max_token_size=8192 # During a SQL upgrade member_role_id will be used to create a # new role that will replace records in the # user_tenant_membership table with explicit role grants. # After migration, the member_role_id will be used in the API # add_user_to_project. (string value) #member_role_id=9fe2ff9ee4384b1894a90878d3e92bab # During a SQL upgrade member_role_id will be used to create a # new role that will replace records in the # user_tenant_membership table with explicit role grants. # After migration, member_role_name will be ignored. (string # value) #member_role_name=_member_ # The value passed as the keyword "rounds" to passlib encrypt # method. (integer value) #crypt_strength=40000 # Set this to True if you want to enable TCP_KEEPALIVE on # server sockets i.e. sockets used by the keystone wsgi server # for client connections. (boolean value) #tcp_keepalive=false # Sets the value of TCP_KEEPIDLE in seconds for each server # socket. Only applies if tcp_keepalive is True. Not supported # on OS X. (integer value) #tcp_keepidle=600 # The maximum number of entities that will be returned in a # collection can be set with list_limit, with no limit set by # default. This global limit may be then overridden for a # specific driver, by specifying a list_limit in the # appropriate section (e.g. [assignment]). (integer value) #list_limit= # Set this to false if you want to enable the ability for # user, group and project entities to be moved between domains # by updating their domain_id. Allowing such movement is not # recommended if the scope of a domain admin is being # restricted by use of an appropriate policy file (see # policy.v3cloudsample as an example). (boolean value) #domain_id_immutable=true # # Options defined in oslo.messaging # # Use durable queues in amqp. (boolean value) # Deprecated group/name - [DEFAULT]/rabbit_durable_queues #amqp_durable_queues=false # Auto-delete queues in amqp. (boolean value) #amqp_auto_delete=false # Size of RPC connection pool. (integer value) #rpc_conn_pool_size=30 # Modules of exceptions that are permitted to be recreated # upon receiving exception data from an rpc call. (list value) #allowed_rpc_exception_modules=oslo.messaging.exceptions,nova.exception,cinder.exception,exceptions # Qpid broker hostname. (string value) #qpid_hostname=localhost # Qpid broker port. (integer value) #qpid_port=5672 # Qpid HA cluster host:port pairs. (list value) #qpid_hosts=$qpid_hostname:$qpid_port # Username for Qpid connection. (string value) #qpid_username= # Password for Qpid connection. (string value) #qpid_password= # Space separated list of SASL mechanisms to use for auth. # (string value) #qpid_sasl_mechanisms= # Seconds between connection keepalive heartbeats. (integer # value) #qpid_heartbeat=60 # Transport to use, either 'tcp' or 'ssl'. (string value) #qpid_protocol=tcp # Whether to disable the Nagle algorithm. (boolean value) #qpid_tcp_nodelay=true # The qpid topology version to use. Version 1 is what was # originally used by impl_qpid. Version 2 includes some # backwards-incompatible changes that allow broker federation # to work. Users should update to version 2 when they are # able to take everything down, as it requires a clean break. # (integer value) #qpid_topology_version=1 # SSL version to use (valid only if SSL enabled). valid values # are TLSv1, SSLv23 and SSLv3. SSLv2 may be available on some # distributions. (string value) #kombu_ssl_version= # SSL key file (valid only if SSL enabled). (string value) #kombu_ssl_keyfile= # SSL cert file (valid only if SSL enabled). (string value) #kombu_ssl_certfile= # SSL certification authority file (valid only if SSL # enabled). (string value) #kombu_ssl_ca_certs= # How long to wait before reconnecting in response to an AMQP # consumer cancel notification. (floating point value) #kombu_reconnect_delay=1.0 # The RabbitMQ broker address where a single node is used. # (string value) #rabbit_host=localhost # The RabbitMQ broker port where a single node is used. # (integer value) #rabbit_port=5672 # RabbitMQ HA cluster host:port pairs. (list value) #rabbit_hosts=$rabbit_host:$rabbit_port # Connect over SSL for RabbitMQ. (boolean value) #rabbit_use_ssl=false # The RabbitMQ userid. (string value) #rabbit_userid=guest # The RabbitMQ password. (string value) #rabbit_password=guest # the RabbitMQ login method (string value) #rabbit_login_method=AMQPLAIN # The RabbitMQ virtual host. (string value) #rabbit_virtual_host=/ # How frequently to retry connecting with RabbitMQ. (integer # value) #rabbit_retry_interval=1 # How long to backoff for between retries when connecting to # RabbitMQ. (integer value) #rabbit_retry_backoff=2 # Maximum number of RabbitMQ connection retries. Default is 0 # (infinite retry count). (integer value) #rabbit_max_retries=0 # Use HA queues in RabbitMQ (x-ha-policy: all). If you change # this option, you must wipe the RabbitMQ database. (boolean # value) #rabbit_ha_queues=false # If passed, use a fake RabbitMQ provider. (boolean value) #fake_rabbit=false # ZeroMQ bind address. Should be a wildcard (*), an ethernet # interface, or IP. The "host" option should point or resolve # to this address. (string value) #rpc_zmq_bind_address=* # MatchMaker driver. (string value) #rpc_zmq_matchmaker=oslo.messaging._drivers.matchmaker.MatchMakerLocalhost # ZeroMQ receiver listening port. (integer value) #rpc_zmq_port=9501 # Number of ZeroMQ contexts, defaults to 1. (integer value) #rpc_zmq_contexts=1 # Maximum number of ingress messages to locally buffer per # topic. Default is unlimited. (integer value) #rpc_zmq_topic_backlog= # Directory for holding IPC sockets. (string value) #rpc_zmq_ipc_dir=/var/run/openstack # Name of this node. Must be a valid hostname, FQDN, or IP # address. Must match "host" option, if running Nova. (string # value) #rpc_zmq_host=keystone # Seconds to wait before a cast expires (TTL). Only supported # by impl_zmq. (integer value) #rpc_cast_timeout=30 # Heartbeat frequency. (integer value) #matchmaker_heartbeat_freq=300 # Heartbeat time-to-live. (integer value) #matchmaker_heartbeat_ttl=600 # Host to locate redis. (string value) #host=127.0.0.1 # Use this port to connect to redis host. (integer value) #port=6379 # Password for Redis server (optional). (string value) #password= # Size of RPC greenthread pool. (integer value) #rpc_thread_pool_size=64 # Driver or drivers to handle sending notifications. (multi # valued) #notification_driver= # AMQP topic used for OpenStack notifications. (list value) # Deprecated group/name - [rpc_notifier2]/topics #notification_topics=notifications # Seconds to wait for a response from a call. (integer value) #rpc_response_timeout=60 # A URL representing the messaging driver to use and its full # configuration. If not set, we fall back to the rpc_backend # option and driver specific configuration. (string value) #transport_url= # The messaging driver to use, defaults to rabbit. Other # drivers include qpid and zmq. (string value) #rpc_backend=rabbit # The default exchange under which topics are scoped. May be # overridden by an exchange name specified in the # transport_url option. (string value) #control_exchange=openstack # # Options defined in keystone.notifications # # Default publisher_id for outgoing notifications (string # value) #default_publisher_id= # # Options defined in keystone.middleware.ec2_token # # URL to get token from ec2 request. (string value) #keystone_ec2_url=http://localhost:5000/v2.0/ec2tokens # Required if EC2 server requires client certificate. (string # value) #keystone_ec2_keyfile= # Client certificate key filename. Required if EC2 server # requires client certificate. (string value) #keystone_ec2_certfile= # A PEM encoded certificate authority to use when verifying # HTTPS connections. Defaults to the system CAs. (string # value) #keystone_ec2_cafile= # Disable SSL certificate verification. (boolean value) #keystone_ec2_insecure=false # # Options defined in keystone.openstack.common.eventlet_backdoor # # Enable eventlet backdoor. Acceptable values are 0, , # and :, where 0 results in listening on a random # tcp port number; results in listening on the # specified port number (and not enabling backdoor if that # port is in use); and : results in listening on # the smallest unused port number within the specified range # of port numbers. The chosen port is displayed in the # service's log file. (string value) #backdoor_port= # # Options defined in keystone.openstack.common.lockutils # # Whether to disable inter-process locks (boolean value) #disable_process_locking=false # Directory to use for lock files. (string value) #lock_path= # # Options defined in keystone.openstack.common.log # # Print debugging output (set logging level to DEBUG instead # of default WARNING level). (boolean value) #debug=false # Print more verbose output (set logging level to INFO instead # of default WARNING level). (boolean value) #verbose=false # Log output to standard error (boolean value) #use_stderr=true # Format string to use for log messages with context (string # value) #logging_context_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s # Format string to use for log messages without context # (string value) #logging_default_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s # Data to append to log format when level is DEBUG (string # value) #logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d # Prefix each line of exception output with this format # (string value) #logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s # List of logger=LEVEL pairs (list value) #default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN # Publish error events (boolean value) #publish_errors=false # Make deprecations fatal (boolean value) #fatal_deprecations=false # If an instance is passed with the log message, format it # like this (string value) #instance_format="[instance: %(uuid)s] " # If an instance UUID is passed with the log message, format # it like this (string value) #instance_uuid_format="[instance: %(uuid)s] " # The name of logging configuration file. It does not disable # existing loggers, but just appends specified logging # configuration to any other existing logging options. Please # see the Python logging module documentation for details on # logging configuration files. (string value) # Deprecated group/name - [DEFAULT]/log_config #log_config_append= # DEPRECATED. A logging.Formatter log message format string # which may use any of the available logging.LogRecord # attributes. This option is deprecated. Please use # logging_context_format_string and # logging_default_format_string instead. (string value) #log_format= # Format string for %%(asctime)s in log records. Default: # %(default)s (string value) #log_date_format=%Y-%m-%d %H:%M:%S # (Optional) Name of log file to output to. If no default is # set, logging will go to stdout. (string value) # Deprecated group/name - [DEFAULT]/logfile #log_file= # (Optional) The base directory used for relative --log-file # paths (string value) # Deprecated group/name - [DEFAULT]/logdir #log_dir= # Use syslog for logging. Existing syslog format is DEPRECATED # during I, and then will be changed in J to honor RFC5424 # (boolean value) #use_syslog=false # (Optional) Use syslog rfc5424 format for logging. If # enabled, will add APP-NAME (RFC5424) before the MSG part of # the syslog message. The old format without APP-NAME is # deprecated in I, and will be removed in J. (boolean value) #use_syslog_rfc_format=false # Syslog facility to receive log lines (string value) #syslog_log_facility=LOG_USER # # Options defined in keystone.openstack.common.policy # # JSON file containing policy (string value) #policy_file=policy.json # Rule enforced when requested rule is not found (string # value) #policy_default_rule=default [assignment] # # Options defined in keystone # # Keystone Assignment backend driver. (string value) #driver= # Toggle for assignment caching. This has no effect unless # global caching is enabled. (boolean value) #caching=true # TTL (in seconds) to cache assignment data. This has no # effect unless global caching is enabled. (integer value) #cache_time= # Maximum number of entities that will be returned in an # assignment collection. (integer value) #list_limit= [auth] # # Options defined in keystone # # Default auth methods. (list value) #methods=external,password,token # The password auth plugin module. (string value) #password=keystone.auth.plugins.password.Password # The token auth plugin module. (string value) #token=keystone.auth.plugins.token.Token # The external (REMOTE_USER) auth plugin module. (string # value) #external=keystone.auth.plugins.external.DefaultDomain [cache] # # Options defined in keystone # # Prefix for building the configuration dictionary for the # cache region. This should not need to be changed unless # there is another dogpile.cache region with the same # configuration name. (string value) #config_prefix=cache.keystone # Default TTL, in seconds, for any cached item in the # dogpile.cache region. This applies to any cached method that # doesn't have an explicit cache expiration time defined for # it. (integer value) #expiration_time=600 # Dogpile.cache backend module. It is recommended that # Memcache (dogpile.cache.memcache) or Redis # (dogpile.cache.redis) be used in production deployments. # Small workloads (single process) like devstack can use the # dogpile.cache.memory backend. (string value) #backend=keystone.common.cache.noop # Use a key-mangling function (sha1) to ensure fixed length # cache-keys. This is toggle-able for debugging purposes, it # is highly recommended to always leave this set to True. # (boolean value) #use_key_mangler=true # Arguments supplied to the backend module. Specify this # option once per argument to be passed to the dogpile.cache # backend. Example format: ":". (multi valued) #backend_argument= # Proxy Classes to import that will affect the way the # dogpile.cache backend functions. See the dogpile.cache # documentation on changing-backend-behavior. Comma delimited # list e.g. my.dogpile.proxy.Class, my.dogpile.proxyClass2. # (list value) #proxies= # Global toggle for all caching using the should_cache_fn # mechanism. (boolean value) #enabled=false # Extra debugging from the cache backend (cache keys, # get/set/delete/etc calls) This is only really useful if you # need to see the specific cache-backend get/set/delete calls # with the keys/values. Typically this should be left set to # False. (boolean value) #debug_cache_backend=false [catalog] # # Options defined in keystone # # Catalog template file name for use with the template catalog # backend. (string value) #template_file=default_catalog.templates # Keystone catalog backend driver. (string value) #driver=keystone.catalog.backends.sql.Catalog # Maximum number of entities that will be returned in a # catalog collection. (integer value) #list_limit= [credential] # # Options defined in keystone # # Keystone Credential backend driver. (string value) #driver=keystone.credential.backends.sql.Credential [database] # # Options defined in keystone.openstack.common.db.options # # The file name to use with SQLite (string value) #sqlite_db=keystone.sqlite # If True, SQLite uses synchronous mode (boolean value) #sqlite_synchronous=true # The backend to use for db (string value) # Deprecated group/name - [DEFAULT]/db_backend #backend=sqlalchemy # The SQLAlchemy connection string used to connect to the # database (string value) # Deprecated group/name - [DEFAULT]/sql_connection # Deprecated group/name - [DATABASE]/sql_connection # Deprecated group/name - [sql]/connection #connection= # The SQL mode to be used for MySQL sessions. This option, # including the default, overrides any server-set SQL mode. To # use whatever SQL mode is set by the server configuration, # set this to no value. Example: mysql_sql_mode= (string # value) #mysql_sql_mode=TRADITIONAL # Timeout before idle sql connections are reaped (integer # value) # Deprecated group/name - [DEFAULT]/sql_idle_timeout # Deprecated group/name - [DATABASE]/sql_idle_timeout # Deprecated group/name - [sql]/idle_timeout #idle_timeout=3600 # Minimum number of SQL connections to keep open in a pool # (integer value) # Deprecated group/name - [DEFAULT]/sql_min_pool_size # Deprecated group/name - [DATABASE]/sql_min_pool_size #min_pool_size=1 # Maximum number of SQL connections to keep open in a pool # (integer value) # Deprecated group/name - [DEFAULT]/sql_max_pool_size # Deprecated group/name - [DATABASE]/sql_max_pool_size #max_pool_size= # Maximum db connection retries during startup. (setting -1 # implies an infinite retry count) (integer value) # Deprecated group/name - [DEFAULT]/sql_max_retries # Deprecated group/name - [DATABASE]/sql_max_retries #max_retries=10 # Interval between retries of opening a sql connection # (integer value) # Deprecated group/name - [DEFAULT]/sql_retry_interval # Deprecated group/name - [DATABASE]/reconnect_interval #retry_interval=10 # If set, use this value for max_overflow with sqlalchemy # (integer value) # Deprecated group/name - [DEFAULT]/sql_max_overflow # Deprecated group/name - [DATABASE]/sqlalchemy_max_overflow #max_overflow= # Verbosity of SQL debugging information. 0=None, # 100=Everything (integer value) # Deprecated group/name - [DEFAULT]/sql_connection_debug #connection_debug=0 # Add python stack traces to SQL as comment strings (boolean # value) # Deprecated group/name - [DEFAULT]/sql_connection_trace #connection_trace=false # If set, use this value for pool_timeout with sqlalchemy # (integer value) # Deprecated group/name - [DATABASE]/sqlalchemy_pool_timeout #pool_timeout= # Enable the experimental use of database reconnect on # connection lost (boolean value) #use_db_reconnect=false # seconds between db connection retries (integer value) #db_retry_interval=1 # Whether to increase interval between db connection retries, # up to db_max_retry_interval (boolean value) #db_inc_retry_interval=true # max seconds between db connection retries, if # db_inc_retry_interval is enabled (integer value) #db_max_retry_interval=10 # maximum db connection retries before error is raised. # (setting -1 implies an infinite retry count) (integer value) #db_max_retries=20 [ec2] # # Options defined in keystone # # Keystone EC2Credential backend driver. (string value) #driver=keystone.contrib.ec2.backends.kvs.Ec2 [endpoint_filter] # # Options defined in keystone # # Keystone Endpoint Filter backend driver (string value) #driver=keystone.contrib.endpoint_filter.backends.sql.EndpointFilter # Toggle to return all active endpoints if no filter exists. # (boolean value) #return_all_endpoints_if_no_filter=true [federation] # # Options defined in keystone # # Keystone Federation backend driver. (string value) #driver=keystone.contrib.federation.backends.sql.Federation # Value to be used when filtering assertion parameters from # the environment. (string value) #assertion_prefix= [identity] # # Options defined in keystone # # This references the domain to use for all Identity API v2 # requests (which are not aware of domains). A domain with # this ID will be created for you by keystone-manage db_sync # in migration 008. The domain referenced by this ID cannot # be deleted on the v3 API, to prevent accidentally breaking # the v2 API. There is nothing special about this domain, # other than the fact that it must exist to order to maintain # support for your v2 clients. (string value) #default_domain_id=default # A subset (or all) of domains can have their own identity # driver, each with their own partial configuration file in a # domain configuration directory. Only values specific to the # domain need to be placed in the domain specific # configuration file. This feature is disabled by default; set # to True to enable. (boolean value) #domain_specific_drivers_enabled=false # Path for Keystone to locate the domain specificidentity # configuration files if domain_specific_drivers_enabled is # set to true. (string value) #domain_config_dir=/etc/keystone/domains # Keystone Identity backend driver. (string value) #driver=keystone.identity.backends.sql.Identity # Maximum supported length for user passwords; decrease to # improve performance. (integer value) #max_password_length=4096 # Maximum number of entities that will be returned in an # identity collection. (integer value) #list_limit= [kvs] # # Options defined in keystone # # Extra dogpile.cache backend modules to register with the # dogpile.cache library. (list value) #backends= # Prefix for building the configuration dictionary for the KVS # region. This should not need to be changed unless there is # another dogpile.cache region with the same configuration # name. (string value) #config_prefix=keystone.kvs # Toggle to disable using a key-mangling function to ensure # fixed length keys. This is toggle-able for debugging # purposes, it is highly recommended to always leave this set # to True. (boolean value) #enable_key_mangler=true # Default lock timeout for distributed locking. (integer # value) #default_lock_timeout=5 [ldap] # # Options defined in keystone # # URL for connecting to the LDAP server. (string value) #url=ldap://localhost # User BindDN to query the LDAP server. (string value) #user= # Password for the BindDN to query the LDAP server. (string # value) #password= # LDAP server suffix (string value) #suffix=cn=example,cn=com # If true, will add a dummy member to groups. This is required # if the objectclass for groups requires the "member" # attribute. (boolean value) #use_dumb_member=false # DN of the "dummy member" to use when "use_dumb_member" is # enabled. (string value) #dumb_member=cn=dumb,dc=nonexistent # allow deleting subtrees. (boolean value) #allow_subtree_delete=false # The LDAP scope for queries, this can be either "one" # (onelevel/singleLevel) or "sub" (subtree/wholeSubtree). # (string value) #query_scope=one # Maximum results per page; a value of zero ("0") disables # paging. (integer value) #page_size=0 # The LDAP dereferencing option for queries. This can be # either "never", "searching", "always", "finding" or # "default". The "default" option falls back to using default # dereferencing configured by your ldap.conf. (string value) #alias_dereferencing=default # Override the system's default referral chasing behavior for # queries. (boolean value) #chase_referrals= # Search base for users. (string value) #user_tree_dn= # LDAP search filter for users. (string value) #user_filter= # LDAP objectClass for users. (string value) #user_objectclass=inetOrgPerson # LDAP attribute mapped to user id. (string value) #user_id_attribute=cn # LDAP attribute mapped to user name. (string value) #user_name_attribute=sn # LDAP attribute mapped to user email. (string value) #user_mail_attribute=email # LDAP attribute mapped to password. (string value) #user_pass_attribute=userPassword # LDAP attribute mapped to user enabled flag. (string value) #user_enabled_attribute=enabled # Bitmask integer to indicate the bit that the enabled value # is stored in if the LDAP server represents "enabled" as a # bit on an integer rather than a boolean. A value of "0" # indicates the mask is not used. If this is not set to "0" # the typical value is "2". This is typically used when # "user_enabled_attribute = userAccountControl". (integer # value) #user_enabled_mask=0 # Default value to enable users. This should match an # appropriate int value if the LDAP server uses non-boolean # (bitmask) values to indicate if a user is enabled or # disabled. If this is not set to "True"the typical value is # "512". This is typically used when "user_enabled_attribute = # userAccountControl". (string value) #user_enabled_default=True # List of attributes stripped off the user on update. (list # value) #user_attribute_ignore=default_project_id,tenants # LDAP attribute mapped to default_project_id for users. # (string value) #user_default_project_id_attribute= # Allow user creation in LDAP backend. (boolean value) #user_allow_create=true # Allow user updates in LDAP backend. (boolean value) #user_allow_update=true # Allow user deletion in LDAP backend. (boolean value) #user_allow_delete=true # If True, Keystone uses an alternative method to determine if # a user is enabled or not by checking if they are a member of # the "user_enabled_emulation_dn" group. (boolean value) #user_enabled_emulation=false # DN of the group entry to hold enabled users when using # enabled emulation. (string value) #user_enabled_emulation_dn= # List of additional LDAP attributes used for mapping # Additional attribute mappings for users. Attribute mapping # format is :, where ldap_attr is the # attribute in the LDAP entry and user_attr is the Identity # API attribute. (list value) #user_additional_attribute_mapping= # Search base for projects (string value) #tenant_tree_dn= # LDAP search filter for projects. (string value) #tenant_filter= # LDAP objectClass for projects. (string value) #tenant_objectclass=groupOfNames # LDAP attribute mapped to project id. (string value) #tenant_id_attribute=cn # LDAP attribute mapped to project membership for user. # (string value) #tenant_member_attribute=member # LDAP attribute mapped to project name. (string value) #tenant_name_attribute=ou # LDAP attribute mapped to project description. (string value) #tenant_desc_attribute=description # LDAP attribute mapped to project enabled. (string value) #tenant_enabled_attribute=enabled # LDAP attribute mapped to project domain_id. (string value) #tenant_domain_id_attribute=businessCategory # List of attributes stripped off the project on update. (list # value) #tenant_attribute_ignore= # Allow tenant creation in LDAP backend. (boolean value) #tenant_allow_create=true # Allow tenant update in LDAP backend. (boolean value) #tenant_allow_update=true # Allow tenant deletion in LDAP backend. (boolean value) #tenant_allow_delete=true # If True, Keystone uses an alternative method to determine if # a project is enabled or not by checking if they are a member # of the "tenant_enabled_emulation_dn" group. (boolean value) #tenant_enabled_emulation=false # DN of the group entry to hold enabled projects when using # enabled emulation. (string value) #tenant_enabled_emulation_dn= # Additional attribute mappings for projects. Attribute # mapping format is :, where ldap_attr # is the attribute in the LDAP entry and user_attr is the # Identity API attribute. (list value) #tenant_additional_attribute_mapping= # Search base for roles. (string value) #role_tree_dn= # LDAP search filter for roles. (string value) #role_filter= # LDAP objectClass for roles. (string value) #role_objectclass=organizationalRole # LDAP attribute mapped to role id. (string value) #role_id_attribute=cn # LDAP attribute mapped to role name. (string value) #role_name_attribute=ou # LDAP attribute mapped to role membership. (string value) #role_member_attribute=roleOccupant # List of attributes stripped off the role on update. (list # value) #role_attribute_ignore= # Allow role creation in LDAP backend. (boolean value) #role_allow_create=true # Allow role update in LDAP backend. (boolean value) #role_allow_update=true # Allow role deletion in LDAP backend. (boolean value) #role_allow_delete=true # Additional attribute mappings for roles. Attribute mapping # format is :, where ldap_attr is the # attribute in the LDAP entry and user_attr is the Identity # API attribute. (list value) #role_additional_attribute_mapping= # Search base for groups. (string value) #group_tree_dn= # LDAP search filter for groups. (string value) #group_filter= # LDAP objectClass for groups. (string value) #group_objectclass=groupOfNames # LDAP attribute mapped to group id. (string value) #group_id_attribute=cn # LDAP attribute mapped to group name. (string value) #group_name_attribute=ou # LDAP attribute mapped to show group membership. (string # value) #group_member_attribute=member # LDAP attribute mapped to group description. (string value) #group_desc_attribute=description # List of attributes stripped off the group on update. (list # value) #group_attribute_ignore= # Allow group creation in LDAP backend. (boolean value) #group_allow_create=true # Allow group update in LDAP backend. (boolean value) #group_allow_update=true # Allow group deletion in LDAP backend. (boolean value) #group_allow_delete=true # Additional attribute mappings for groups. Attribute mapping # format is :, where ldap_attr is the # attribute in the LDAP entry and user_attr is the Identity # API attribute. (list value) #group_additional_attribute_mapping= # CA certificate file path for communicating with LDAP # servers. (string value) #tls_cacertfile= # CA certificate directory path for communicating with LDAP # servers. (string value) #tls_cacertdir= # Enable TLS for communicating with LDAP servers. (boolean # value) #use_tls=false # valid options for tls_req_cert are demand, never, and allow. # (string value) #tls_req_cert=demand [matchmaker_ring] # # Options defined in oslo.messaging # # Matchmaker ring file (JSON). (string value) # Deprecated group/name - [DEFAULT]/matchmaker_ringfile #ringfile=/etc/oslo/matchmaker_ring.json [memcache] # # Options defined in keystone # # Memcache servers in the format of "host:port" (list value) #servers=localhost:11211 # Number of compare-and-set attempts to make when using # compare-and-set in the token memcache back end. (integer # value) #max_compare_and_set_retry=16 [oauth1] # # Options defined in keystone # # Keystone Credential backend driver. (string value) #driver=keystone.contrib.oauth1.backends.sql.OAuth1 # Duration (in seconds) for the OAuth Request Token. (integer # value) #request_token_duration=28800 # Duration (in seconds) for the OAuth Access Token. (integer # value) #access_token_duration=86400 [os_inherit] # # Options defined in keystone # # role-assignment inheritance to projects from owning domain # can be optionally enabled. (boolean value) #enabled=false [paste_deploy] # # Options defined in keystone # # Name of the paste configuration file that defines the # available pipelines. (string value) #config_file=keystone-paste.ini [policy] # # Options defined in keystone # # Keystone Policy backend driver. (string value) #driver=keystone.policy.backends.sql.Policy # Maximum number of entities that will be returned in a policy # collection. (integer value) #list_limit= [revoke] # # Options defined in keystone # # An implementation of the backend for persisting revocation # events. (string value) #driver=keystone.contrib.revoke.backends.kvs.Revoke # This value (calculated in seconds) is added to token # expiration before a revocation event may be removed from the # backend. (integer value) #expiration_buffer=1800 # Toggle for revocation event cacheing. This has no effect # unless global caching is enabled. (boolean value) #caching=true [signing] # # Options defined in keystone # # Deprecated in favor of provider in the [token] section. # (string value) #token_format= # Path of the certfile for token signing. (string value) #certfile=/etc/keystone/ssl/certs/signing_cert.pem # Path of the keyfile for token signing. (string value) #keyfile=/etc/keystone/ssl/private/signing_key.pem # Path of the CA for token signing. (string value) #ca_certs=/etc/keystone/ssl/certs/ca.pem # Path of the CA Key for token signing. (string value) #ca_key=/etc/keystone/ssl/private/cakey.pem # Key Size (in bits) for token signing cert (auto generated # certificate). (integer value) #key_size=2048 # Day the token signing cert is valid for (auto generated # certificate). (integer value) #valid_days=3650 # Certificate Subject (auto generated certificate) for token # signing. (string value) #cert_subject=/C=US/ST=Unset/L=Unset/O=Unset/CN=www.example.com [ssl] # # Options defined in keystone # # Toggle for SSL support on the keystone eventlet servers. # (boolean value) #enable=false # Path of the certfile for SSL. (string value) #certfile=/etc/keystone/ssl/certs/keystone.pem # Path of the keyfile for SSL. (string value) #keyfile=/etc/keystone/ssl/private/keystonekey.pem # Path of the ca cert file for SSL. (string value) #ca_certs=/etc/keystone/ssl/certs/ca.pem # Path of the CA key file for SSL. (string value) #ca_key=/etc/keystone/ssl/private/cakey.pem # Require client certificate. (boolean value) #cert_required=false # SSL Key Length (in bits) (auto generated certificate). # (integer value) #key_size=1024 # Days the certificate is valid for once signed (auto # generated certificate). (integer value) #valid_days=3650 # SSL Certificate Subject (auto generated certificate). # (string value) #cert_subject=/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost [stats] # # Options defined in keystone # # Keystone stats backend driver. (string value) #driver=keystone.contrib.stats.backends.kvs.Stats [token] # # Options defined in keystone # # External auth mechanisms that should add bind information to # token e.g. kerberos, x509. (list value) #bind= # Enforcement policy on tokens presented to keystone with bind # information. One of disabled, permissive, strict, required # or a specifically required bind mode e.g. kerberos or x509 # to require binding to that authentication. (string value) #enforce_token_bind=permissive # Amount of time a token should remain valid (in seconds). # (integer value) #expiration=3600 # Controls the token construction, validation, and revocation # operations. Core providers are # "keystone.token.providers.[pki|uuid].Provider". (string # value) #provider= # Keystone Token persistence backend driver. (string value) #driver=keystone.token.backends.sql.Token # Toggle for token system cacheing. This has no effect unless # global caching is enabled. (boolean value) #caching=true # Time to cache the revocation list and the revocation events # if revoke extension is enabled (in seconds). This has no # effect unless global and token caching are enabled. (integer # value) #revocation_cache_time=3600 # Time to cache tokens (in seconds). This has no effect unless # global and token caching are enabled. (integer value) #cache_time= # Revoke token by token identifier. Setting revoke_by_id to # True enables various forms of enumerating tokens, e.g. `list # tokens for user`. These enumerations are processed to # determine the list of tokens to revoke. Only disable if # you are switching to using the Revoke extension with a # backend other than KVS, which stores events in memory. # (boolean value) #revoke_by_id=true [trust] # # Options defined in keystone # # delegation and impersonation features can be optionally # disabled. (boolean value) #enabled=true # Keystone Trust backend driver. (string value) #driver=keystone.trust.backends.sql.Trust keystone-2014.1/etc/default_catalog.templates0000664000175400017540000000300412323716267022417 0ustar jenkinsjenkins00000000000000# config for templated.Catalog, using camelCase because I don't want to do # translations for keystone compat catalog.RegionOne.identity.publicURL = http://localhost:$(public_port)s/v2.0 catalog.RegionOne.identity.adminURL = http://localhost:$(admin_port)s/v2.0 catalog.RegionOne.identity.internalURL = http://localhost:$(public_port)s/v2.0 catalog.RegionOne.identity.name = Identity Service # fake compute service for now to help novaclient tests work catalog.RegionOne.compute.publicURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s catalog.RegionOne.compute.adminURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s catalog.RegionOne.compute.name = Compute Service catalog.RegionOne.volume.publicURL = http://localhost:8776/v1/$(tenant_id)s catalog.RegionOne.volume.adminURL = http://localhost:8776/v1/$(tenant_id)s catalog.RegionOne.volume.internalURL = http://localhost:8776/v1/$(tenant_id)s catalog.RegionOne.volume.name = Volume Service catalog.RegionOne.ec2.publicURL = http://localhost:8773/services/Cloud catalog.RegionOne.ec2.adminURL = http://localhost:8773/services/Admin catalog.RegionOne.ec2.internalURL = http://localhost:8773/services/Cloud catalog.RegionOne.ec2.name = EC2 Service catalog.RegionOne.image.publicURL = http://localhost:9292/v1 catalog.RegionOne.image.adminURL = http://localhost:9292/v1 catalog.RegionOne.image.internalURL = http://localhost:9292/v1 catalog.RegionOne.image.name = Image Service keystone-2014.1/etc/keystone-paste.ini0000664000175400017540000000706312323716267021046 0ustar jenkinsjenkins00000000000000# Keystone PasteDeploy configuration file. [filter:debug] paste.filter_factory = keystone.common.wsgi:Debug.factory [filter:build_auth_context] paste.filter_factory = keystone.middleware:AuthContextMiddleware.factory [filter:token_auth] paste.filter_factory = keystone.middleware:TokenAuthMiddleware.factory [filter:admin_token_auth] paste.filter_factory = keystone.middleware:AdminTokenAuthMiddleware.factory [filter:xml_body] paste.filter_factory = keystone.middleware:XmlBodyMiddleware.factory [filter:xml_body_v2] paste.filter_factory = keystone.middleware:XmlBodyMiddlewareV2.factory [filter:xml_body_v3] paste.filter_factory = keystone.middleware:XmlBodyMiddlewareV3.factory [filter:json_body] paste.filter_factory = keystone.middleware:JsonBodyMiddleware.factory [filter:user_crud_extension] paste.filter_factory = keystone.contrib.user_crud:CrudExtension.factory [filter:crud_extension] paste.filter_factory = keystone.contrib.admin_crud:CrudExtension.factory [filter:ec2_extension] paste.filter_factory = keystone.contrib.ec2:Ec2Extension.factory [filter:ec2_extension_v3] paste.filter_factory = keystone.contrib.ec2:Ec2ExtensionV3.factory [filter:federation_extension] paste.filter_factory = keystone.contrib.federation.routers:FederationExtension.factory [filter:oauth1_extension] paste.filter_factory = keystone.contrib.oauth1.routers:OAuth1Extension.factory [filter:s3_extension] paste.filter_factory = keystone.contrib.s3:S3Extension.factory [filter:endpoint_filter_extension] paste.filter_factory = keystone.contrib.endpoint_filter.routers:EndpointFilterExtension.factory [filter:simple_cert_extension] paste.filter_factory = keystone.contrib.simple_cert:SimpleCertExtension.factory [filter:revoke_extension] paste.filter_factory = keystone.contrib.revoke.routers:RevokeExtension.factory [filter:url_normalize] paste.filter_factory = keystone.middleware:NormalizingFilter.factory [filter:sizelimit] paste.filter_factory = keystone.middleware:RequestBodySizeLimiter.factory [filter:stats_monitoring] paste.filter_factory = keystone.contrib.stats:StatsMiddleware.factory [filter:stats_reporting] paste.filter_factory = keystone.contrib.stats:StatsExtension.factory [filter:access_log] paste.filter_factory = keystone.contrib.access:AccessLogMiddleware.factory [app:public_service] paste.app_factory = keystone.service:public_app_factory [app:service_v3] paste.app_factory = keystone.service:v3_app_factory [app:admin_service] paste.app_factory = keystone.service:admin_app_factory [pipeline:public_api] pipeline = sizelimit url_normalize build_auth_context token_auth admin_token_auth xml_body_v2 json_body ec2_extension user_crud_extension public_service [pipeline:admin_api] pipeline = sizelimit url_normalize build_auth_context token_auth admin_token_auth xml_body_v2 json_body ec2_extension s3_extension crud_extension admin_service [pipeline:api_v3] pipeline = sizelimit url_normalize build_auth_context token_auth admin_token_auth xml_body_v3 json_body ec2_extension_v3 s3_extension simple_cert_extension service_v3 [app:public_version_service] paste.app_factory = keystone.service:public_version_app_factory [app:admin_version_service] paste.app_factory = keystone.service:admin_version_app_factory [pipeline:public_version_api] pipeline = sizelimit url_normalize xml_body public_version_service [pipeline:admin_version_api] pipeline = sizelimit url_normalize xml_body admin_version_service [composite:main] use = egg:Paste#urlmap /v2.0 = public_api /v3 = api_v3 / = public_version_api [composite:admin] use = egg:Paste#urlmap /v2.0 = admin_api /v3 = api_v3 / = admin_version_api keystone-2014.1/etc/policy.json0000664000175400017540000001437512323716267017570 0ustar jenkinsjenkins00000000000000{ "admin_required": "role:admin or is_admin:1", "service_role": "role:service", "service_or_admin": "rule:admin_required or rule:service_role", "owner" : "user_id:%(user_id)s", "admin_or_owner": "rule:admin_required or rule:owner", "default": "rule:admin_required", "identity:get_region": "", "identity:list_regions": "", "identity:create_region": "rule:admin_required", "identity:update_region": "rule:admin_required", "identity:delete_region": "rule:admin_required", "identity:get_service": "rule:admin_required", "identity:list_services": "rule:admin_required", "identity:create_service": "rule:admin_required", "identity:update_service": "rule:admin_required", "identity:delete_service": "rule:admin_required", "identity:get_endpoint": "rule:admin_required", "identity:list_endpoints": "rule:admin_required", "identity:create_endpoint": "rule:admin_required", "identity:update_endpoint": "rule:admin_required", "identity:delete_endpoint": "rule:admin_required", "identity:get_domain": "rule:admin_required", "identity:list_domains": "rule:admin_required", "identity:create_domain": "rule:admin_required", "identity:update_domain": "rule:admin_required", "identity:delete_domain": "rule:admin_required", "identity:get_project": "rule:admin_required", "identity:list_projects": "rule:admin_required", "identity:list_user_projects": "rule:admin_or_owner", "identity:create_project": "rule:admin_required", "identity:update_project": "rule:admin_required", "identity:delete_project": "rule:admin_required", "identity:get_user": "rule:admin_required", "identity:list_users": "rule:admin_required", "identity:create_user": "rule:admin_required", "identity:update_user": "rule:admin_required", "identity:delete_user": "rule:admin_required", "identity:change_password": "rule:admin_or_owner", "identity:get_group": "rule:admin_required", "identity:list_groups": "rule:admin_required", "identity:list_groups_for_user": "rule:admin_or_owner", "identity:create_group": "rule:admin_required", "identity:update_group": "rule:admin_required", "identity:delete_group": "rule:admin_required", "identity:list_users_in_group": "rule:admin_required", "identity:remove_user_from_group": "rule:admin_required", "identity:check_user_in_group": "rule:admin_required", "identity:add_user_to_group": "rule:admin_required", "identity:get_credential": "rule:admin_required", "identity:list_credentials": "rule:admin_required", "identity:create_credential": "rule:admin_required", "identity:update_credential": "rule:admin_required", "identity:delete_credential": "rule:admin_required", "identity:ec2_get_credential": "rule:admin_or_owner", "identity:ec2_list_credentials": "rule:admin_or_owner", "identity:ec2_create_credential": "rule:admin_or_owner", "identity:ec2_delete_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)", "identity:get_role": "rule:admin_required", "identity:list_roles": "rule:admin_required", "identity:create_role": "rule:admin_required", "identity:update_role": "rule:admin_required", "identity:delete_role": "rule:admin_required", "identity:check_grant": "rule:admin_required", "identity:list_grants": "rule:admin_required", "identity:create_grant": "rule:admin_required", "identity:revoke_grant": "rule:admin_required", "identity:list_role_assignments": "rule:admin_required", "identity:get_policy": "rule:admin_required", "identity:list_policies": "rule:admin_required", "identity:create_policy": "rule:admin_required", "identity:update_policy": "rule:admin_required", "identity:delete_policy": "rule:admin_required", "identity:check_token": "rule:admin_required", "identity:validate_token": "rule:service_or_admin", "identity:validate_token_head": "rule:service_or_admin", "identity:revocation_list": "rule:service_or_admin", "identity:revoke_token": "rule:admin_or_owner", "identity:create_trust": "user_id:%(trust.trustor_user_id)s", "identity:get_trust": "rule:admin_or_owner", "identity:list_trusts": "", "identity:list_roles_for_trust": "", "identity:check_role_for_trust": "", "identity:get_role_for_trust": "", "identity:delete_trust": "", "identity:create_consumer": "rule:admin_required", "identity:get_consumer": "rule:admin_required", "identity:list_consumers": "rule:admin_required", "identity:delete_consumer": "rule:admin_required", "identity:update_consumer": "rule:admin_required", "identity:authorize_request_token": "rule:admin_required", "identity:list_access_token_roles": "rule:admin_required", "identity:get_access_token_role": "rule:admin_required", "identity:list_access_tokens": "rule:admin_required", "identity:get_access_token": "rule:admin_required", "identity:delete_access_token": "rule:admin_required", "identity:list_projects_for_endpoint": "rule:admin_required", "identity:add_endpoint_to_project": "rule:admin_required", "identity:check_endpoint_in_project": "rule:admin_required", "identity:list_endpoints_for_project": "rule:admin_required", "identity:remove_endpoint_from_project": "rule:admin_required", "identity:create_identity_provider": "rule:admin_required", "identity:list_identity_providers": "rule:admin_required", "identity:get_identity_providers": "rule:admin_required", "identity:update_identity_provider": "rule:admin_required", "identity:delete_identity_provider": "rule:admin_required", "identity:create_protocol": "rule:admin_required", "identity:update_protocol": "rule:admin_required", "identity:get_protocol": "rule:admin_required", "identity:list_protocols": "rule:admin_required", "identity:delete_protocol": "rule:admin_required", "identity:create_mapping": "rule:admin_required", "identity:get_mapping": "rule:admin_required", "identity:list_mappings": "rule:admin_required", "identity:delete_mapping": "rule:admin_required", "identity:update_mapping": "rule:admin_required", "identity:list_projects_for_groups": "", "identity:list_domains_for_groups": "", "identity:list_revoke_events": "" } keystone-2014.1/etc/policy.v3cloudsample.json0000664000175400017540000002151012323716267022335 0ustar jenkinsjenkins00000000000000{ "admin_required": "role:admin", "cloud_admin": "rule:admin_required and domain_id:admin_domain_id", "service_role": "role:service", "service_or_admin": "rule:admin_required or rule:service_role", "owner" : "user_id:%(user_id)s or user_id:%(target.token.user_id)s", "admin_or_owner": "(rule:admin_required and domain_id:%(target.token.user.domain.id)s) or rule:owner", "admin_or_cloud_admin": "rule:admin_required or rule:cloud_admin", "admin_and_matching_domain_id": "rule:admin_required and domain_id:%(domain_id)s", "default": "rule:admin_required", "identity:get_region": "", "identity:list_regions": "", "identity:create_region": "rule:admin_or_cloud_admin", "identity:update_region": "rule:admin_or_cloud_admin", "identity:delete_region": "rule:admin_or_cloud_admin", "identity:get_service": "rule:admin_or_cloud_admin", "identity:list_services": "rule:admin_or_cloud_admin", "identity:create_service": "rule:cloud_admin", "identity:update_service": "rule:cloud_admin", "identity:delete_service": "rule:cloud_admin", "identity:get_endpoint": "rule:admin_or_cloud_admin", "identity:list_endpoints": "rule:admin_or_cloud_admin", "identity:create_endpoint": "rule:cloud_admin", "identity:update_endpoint": "rule:cloud_admin", "identity:delete_endpoint": "rule:cloud_admin", "identity:get_domain": "rule:cloud_admin", "identity:list_domains": "rule:cloud_admin", "identity:create_domain": "rule:cloud_admin", "identity:update_domain": "rule:cloud_admin", "identity:delete_domain": "rule:cloud_admin", "admin_and_matching_target_project_domain_id": "rule:admin_required and domain_id:%(target.project.domain_id)s", "admin_and_matching_project_domain_id": "rule:admin_required and domain_id:%(project.domain_id)s", "identity:get_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", "identity:list_projects": "rule:admin_required and domain_id:%(domain_id)s", "identity:list_user_projects": "rule:owner or rule:admin_and_matching_domain_id", "identity:create_project": "rule:cloud_admin or rule:admin_and_matching_project_domain_id", "identity:update_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", "identity:delete_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id", "admin_and_matching_target_user_domain_id": "rule:admin_required and domain_id:%(target.user.domain_id)s", "admin_and_matching_user_domain_id": "rule:admin_required and domain_id:%(user.domain_id)s", "identity:get_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id", "identity:list_users": "rule:cloud_admin or rule:admin_and_matching_domain_id", "identity:create_user": "rule:cloud_admin or rule:admin_and_matching_user_domain_id", "identity:update_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id", "identity:delete_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id", "admin_and_matching_target_group_domain_id": "rule:admin_required and domain_id:%(target.group.domain_id)s", "admin_and_matching_group_domain_id": "rule:admin_required and domain_id:%(group.domain_id)s", "identity:get_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:list_groups": "rule:cloud_admin or rule:admin_and_matching_domain_id", "identity:list_groups_for_user": "rule:owner or (rule:admin_required and domain_id:%(domain_id)s)", "identity:create_group": "rule:cloud_admin or rule:admin_and_matching_group_domain_id", "identity:update_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:delete_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:list_users_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:remove_user_from_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:check_user_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:add_user_to_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id", "identity:get_credential": "rule:admin_required", "identity:list_credentials": "rule:admin_required", "identity:create_credential": "rule:admin_required", "identity:update_credential": "rule:admin_required", "identity:delete_credential": "rule:admin_required", "identity:ec2_get_credential": "rule:admin_or_cloud_admin or rule:owner", "identity:ec2_list_credentials": "rule:admin_or_cloud_admin or rule:owner", "identity:ec2_create_credential": "rule:admin_or_cloud_admin or rule:owner", "identity:ec2_delete_credential": "(rule:admin_or_cloud_admin or rule:owner) or (rule:owner and user_id:%(target.credential.user_id)s)", "identity:get_role": "rule:admin_or_cloud_admin", "identity:list_roles": "rule:admin_or_cloud_admin", "identity:create_role": "rule:cloud_admin", "identity:update_role": "rule:cloud_admin", "identity:delete_role": "rule:cloud_admin", "domain_admin_for_grants": "rule:admin_required and (domain_id:%(domain_id)s or domain_id:%(target.project.domain_id)s)", "project_admin_for_grants": "rule:admin_required and project_id:%(project_id)s", "identity:check_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", "identity:list_grants": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", "identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", "identity:revoke_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants", "admin_on_domain_filter" : "rule:cloud_admin or (rule:admin_required and domain_id:%(scope.domain.id)s)", "admin_on_project_filter" : "rule:cloud_admin or (rule:admin_required and project_id:%(scope.project.id)s)", "identity:list_role_assignments": "rule:admin_on_domain_filter or rule:admin_on_project_filter", "identity:get_policy": "rule:cloud_admin", "identity:list_policies": "rule:cloud_admin", "identity:create_policy": "rule:cloud_admin", "identity:update_policy": "rule:cloud_admin", "identity:delete_policy": "rule:cloud_admin", "identity:change_password": "rule:owner", "identity:check_token": "rule:admin_or_owner", "identity:validate_token": "rule:service_or_admin", "identity:validate_token_head": "rule:service_or_admin", "identity:revocation_list": "rule:service_or_admin", "identity:revoke_token": "rule:admin_or_owner", "identity:create_trust": "user_id:%(trust.trustor_user_id)s", "identity:get_trust": "rule:admin_or_owner", "identity:list_trusts": "", "identity:list_roles_for_trust": "", "identity:check_role_for_trust": "", "identity:get_role_for_trust": "", "identity:delete_trust": "", "identity:create_consumer": "rule:admin_required", "identity:get_consumer": "rule:admin_required", "identity:list_consumers": "rule:admin_required", "identity:delete_consumer": "rule:admin_required", "identity:update_consumer": "rule:admin_required", "identity:authorize_request_token": "rule:admin_required", "identity:list_access_token_roles": "rule:admin_required", "identity:get_access_token_role": "rule:admin_required", "identity:list_access_tokens": "rule:admin_required", "identity:get_access_token": "rule:admin_required", "identity:delete_access_token": "rule:admin_required", "identity:list_projects_for_endpoint": "rule:admin_required", "identity:add_endpoint_to_project": "rule:admin_required", "identity:check_endpoint_in_project": "rule:admin_required", "identity:list_endpoints_for_project": "rule:admin_required", "identity:remove_endpoint_from_project": "rule:admin_required", "identity:create_identity_provider": "rule:admin_required", "identity:list_identity_providers": "rule:admin_required", "identity:get_identity_providers": "rule:admin_required", "identity:update_identity_provider": "rule:admin_required", "identity:delete_identity_provider": "rule:admin_required", "identity:create_protocol": "rule:admin_required", "identity:update_protocol": "rule:admin_required", "identity:get_protocol": "rule:admin_required", "identity:list_protocols": "rule:admin_required", "identity:delete_protocol": "rule:admin_required", "identity:create_mapping": "rule:admin_required", "identity:get_mapping": "rule:admin_required", "identity:list_mappings": "rule:admin_required", "identity:delete_mapping": "rule:admin_required", "identity:update_mapping": "rule:admin_required", "identity:list_projects_for_groups": "", "identity:list_domains_for_groups": "", "identity:list_revoke_events": "" } keystone-2014.1/LICENSE0000664000175400017540000002363712323716267015631 0ustar jenkinsjenkins00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. keystone-2014.1/babel.cfg0000664000175400017540000000002012323716267016327 0ustar jenkinsjenkins00000000000000[python: **.py] keystone-2014.1/requirements.txt0000664000175400017540000000062112323716272020070 0ustar jenkinsjenkins00000000000000# keystone dependencies pbr>=0.6,<1.0 WebOb>=1.2.3 eventlet>=0.13.0 greenlet>=0.3.2 netaddr>=0.7.6 PasteDeploy>=1.5.0 Paste Routes>=1.12.3 six>=1.5.2 SQLAlchemy>=0.7.8,<=0.9.99 sqlalchemy-migrate>=0.8.2,!=0.8.4 passlib lxml>=2.3 iso8601>=0.1.9 python-keystoneclient>=0.7.0 oslo.config>=1.2.0 oslo.messaging>=1.3.0a9 Babel>=1.3 oauthlib>=0.6 dogpile.cache>=0.5.0 jsonschema>=2.0.0,<3.0.0 pycadf>=0.4.1 keystone-2014.1/httpd/0000775000175400017540000000000012323716511015724 5ustar jenkinsjenkins00000000000000keystone-2014.1/httpd/README0000664000175400017540000000014012323716267016607 0ustar jenkinsjenkins00000000000000Documentation how to set up Keystone to run with Apache HTTPD is in doc/source/apache-httpd.rst keystone-2014.1/httpd/keystone.py0000664000175400017540000000350112323716267020146 0ustar jenkinsjenkins00000000000000# Copyright 2013 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. import logging import os from paste import deploy from keystone.openstack.common import gettextutils # NOTE(dstanek): gettextutils.enable_lazy() must be called before # gettextutils._() is called to ensure it has the desired lazy lookup # behavior. This includes cases, like keystone.exceptions, where # gettextutils._() is called at import time. gettextutils.enable_lazy() from keystone.common import dependency from keystone.common import environment from keystone.common import sql from keystone import config from keystone.openstack.common import log from keystone import service CONF = config.CONF config.configure() sql.initialize() config.set_default_for_default_log_levels() CONF(project='keystone') config.setup_logging() environment.use_stdlib() name = os.path.basename(__file__) if CONF.debug: CONF.log_opt_values(log.getLogger(CONF.prog), logging.DEBUG) drivers = service.load_backends() # NOTE(ldbragst): 'application' is required in this context by WSGI spec. # The following is a reference to Python Paste Deploy documentation # http://pythonpaste.org/deploy/ application = deploy.loadapp('config:%s' % config.find_paste_config(), name=name) dependency.resolve_future_dependencies() keystone-2014.1/httpd/wsgi-keystone.conf0000664000175400017540000000030312323716267021407 0ustar jenkinsjenkins00000000000000WSGIScriptAlias /keystone/main /var/www/cgi-bin/keystone/main WSGIScriptAlias /keystone/admin /var/www/cgi-bin/keystone/admin NSSRequireSSL Authtype none keystone-2014.1/keystone.egg-info/0000775000175400017540000000000012323716511020134 5ustar jenkinsjenkins00000000000000keystone-2014.1/keystone.egg-info/dependency_links.txt0000664000175400017540000000000112323716511024202 0ustar jenkinsjenkins00000000000000 keystone-2014.1/keystone.egg-info/not-zip-safe0000664000175400017540000000000112323716505022365 0ustar jenkinsjenkins00000000000000 keystone-2014.1/keystone.egg-info/PKG-INFO0000664000175400017540000000470312323716511021235 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: keystone Version: 2014.1 Summary: OpenStack Identity Home-page: http://www.openstack.org/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ================== OpenStack Keystone ================== Keystone provides authentication, authorization and service discovery mechanisms via HTTP primarily for use by projects in the OpenStack family. It is most commonly deployed as an HTTP interface to existing identity systems, such as LDAP. Developer documentation, the source of which is in ``doc/source/``, is published at: http://keystone.openstack.org/ The API specification is available at: https://github.com/openstack/identity-api The API documentation is available at: http://api.openstack.org/api-ref-identity.html The canonical client library is available at: https://github.com/openstack/python-keystoneclient Documentation for cloud administrators is available at: http://docs.openstack.org/ The source of documentation for cloud administrators is available at: https://github.com/openstack/openstack-manuals Information about our team meeting is available at: https://wiki.openstack.org/wiki/Meetings/KeystoneMeeting Bugs and feature requests are tracked on Launchpad at: https://bugs.launchpad.net/keystone Future design work is tracked at: https://blueprints.launchpad.net/keystone Contributors are encouraged to join IRC (``#openstack-keystone`` on freenode): https://wiki.openstack.org/wiki/IRC For information on contributing to Keystone, see ``CONTRIBUTING.rst``. Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 2.6 keystone-2014.1/keystone.egg-info/entry_points.txt0000664000175400017540000000010012323716511023421 0ustar jenkinsjenkins00000000000000[oslo.config.opts] keystone = keystone.common.config:list_opts keystone-2014.1/keystone.egg-info/top_level.txt0000664000175400017540000000001112323716511022656 0ustar jenkinsjenkins00000000000000keystone keystone-2014.1/keystone.egg-info/requires.txt0000664000175400017540000000057012323716511022536 0ustar jenkinsjenkins00000000000000pbr>=0.6,<1.0 WebOb>=1.2.3 eventlet>=0.13.0 greenlet>=0.3.2 netaddr>=0.7.6 PasteDeploy>=1.5.0 Paste Routes>=1.12.3 six>=1.5.2 SQLAlchemy>=0.7.8,<=0.9.99 sqlalchemy-migrate>=0.8.2,!=0.8.4 passlib lxml>=2.3 iso8601>=0.1.9 python-keystoneclient>=0.7.0 oslo.config>=1.2.0 oslo.messaging>=1.3.0a9 Babel>=1.3 oauthlib>=0.6 dogpile.cache>=0.5.0 jsonschema>=2.0.0,<3.0.0 pycadf>=0.4.1keystone-2014.1/keystone.egg-info/SOURCES.txt0000664000175400017540000005302512323716511022025 0ustar jenkinsjenkins00000000000000.coveragerc .mailmap .testr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE MANIFEST.in README.rst babel.cfg openstack-common.conf requirements.txt run_tests.sh setup.cfg setup.py test-requirements.txt tox.ini bin/keystone-all bin/keystone-manage doc/Makefile doc/README.rst doc/ext/__init__.py doc/ext/apidoc.py doc/source/apache-httpd.rst doc/source/api_curl_examples.rst doc/source/architecture.rst doc/source/community.rst doc/source/conf.py doc/source/configuration.rst doc/source/configuringservices.rst doc/source/developing.rst doc/source/event_notifications.rst doc/source/extension_development.rst doc/source/external-auth.rst doc/source/index.rst doc/source/installing.rst doc/source/middlewarearchitecture.rst doc/source/setup.rst doc/source/extensions/endpoint_filter-configuration.rst doc/source/extensions/federation-configuration.rst doc/source/extensions/oauth1-configuration.rst doc/source/extensions/revoke-configuration.rst doc/source/images/authComp.png doc/source/images/authComp.svg doc/source/images/graphs_authComp.png doc/source/images/graphs_authComp.svg doc/source/images/graphs_authCompDelegate.png doc/source/images/graphs_authCompDelegate.svg doc/source/man/keystone-all.rst doc/source/man/keystone-manage.rst doc/source/static/basic.css doc/source/static/default.css doc/source/static/header-line.gif doc/source/static/header_bg.jpg doc/source/static/jquery.tweet.js doc/source/static/nature.css doc/source/static/openstack_logo.png doc/source/static/tweaks.css etc/default_catalog.templates etc/keystone-paste.ini etc/keystone.conf.sample etc/logging.conf.sample etc/policy.json etc/policy.v3cloudsample.json examples/pki/gen_pki.sh examples/pki/certs/cacert.pem examples/pki/certs/middleware.pem examples/pki/certs/signing_cert.pem examples/pki/certs/ssl_cert.pem examples/pki/cms/auth_token_revoked.json examples/pki/cms/auth_token_revoked.pem examples/pki/cms/auth_token_scoped.json examples/pki/cms/auth_token_scoped.pem examples/pki/cms/auth_token_unscoped.json examples/pki/cms/auth_token_unscoped.pem examples/pki/cms/revocation_list.json examples/pki/cms/revocation_list.pem examples/pki/private/cakey.pem examples/pki/private/signing_key.pem examples/pki/private/ssl_key.pem httpd/README httpd/keystone.py httpd/wsgi-keystone.conf keystone/__init__.py keystone/clean.py keystone/cli.py keystone/config.py keystone/controllers.py keystone/exception.py keystone/notifications.py keystone/routers.py keystone/service.py keystone.egg-info/PKG-INFO keystone.egg-info/SOURCES.txt keystone.egg-info/dependency_links.txt keystone.egg-info/entry_points.txt keystone.egg-info/not-zip-safe keystone.egg-info/requires.txt keystone.egg-info/top_level.txt keystone/assignment/__init__.py keystone/assignment/controllers.py keystone/assignment/core.py keystone/assignment/routers.py keystone/assignment/backends/__init__.py keystone/assignment/backends/kvs.py keystone/assignment/backends/ldap.py keystone/assignment/backends/sql.py keystone/auth/__init__.py keystone/auth/controllers.py keystone/auth/core.py keystone/auth/routers.py keystone/auth/plugins/__init__.py keystone/auth/plugins/external.py keystone/auth/plugins/oauth1.py keystone/auth/plugins/password.py keystone/auth/plugins/saml2.py keystone/auth/plugins/token.py keystone/catalog/__init__.py keystone/catalog/controllers.py keystone/catalog/core.py keystone/catalog/routers.py keystone/catalog/backends/__init__.py keystone/catalog/backends/kvs.py keystone/catalog/backends/sql.py keystone/catalog/backends/templated.py keystone/common/__init__.py keystone/common/authorization.py keystone/common/base64utils.py keystone/common/config.py keystone/common/controller.py keystone/common/dependency.py keystone/common/driver_hints.py keystone/common/extension.py keystone/common/manager.py keystone/common/models.py keystone/common/openssl.py keystone/common/pemutils.py keystone/common/router.py keystone/common/serializer.py keystone/common/systemd.py keystone/common/utils.py keystone/common/wsgi.py keystone/common/cache/__init__.py keystone/common/cache/core.py keystone/common/cache/backends/__init__.py keystone/common/cache/backends/mongo.py keystone/common/cache/backends/noop.py keystone/common/environment/__init__.py keystone/common/environment/eventlet_server.py keystone/common/kvs/__init__.py keystone/common/kvs/core.py keystone/common/kvs/legacy.py keystone/common/kvs/backends/__init__.py keystone/common/kvs/backends/inmemdb.py keystone/common/kvs/backends/memcached.py keystone/common/ldap/__init__.py keystone/common/ldap/core.py keystone/common/sql/__init__.py keystone/common/sql/core.py keystone/common/sql/migration_helpers.py keystone/common/sql/migrate_repo/README keystone/common/sql/migrate_repo/__init__.py keystone/common/sql/migrate_repo/manage.py keystone/common/sql/migrate_repo/migrate.cfg keystone/common/sql/migrate_repo/versions/001_add_initial_tables.py keystone/common/sql/migrate_repo/versions/002_sqlite_downgrade.sql keystone/common/sql/migrate_repo/versions/002_sqlite_upgrade.sql keystone/common/sql/migrate_repo/versions/002_token_id_hash.py keystone/common/sql/migrate_repo/versions/003_sqlite_upgrade.sql keystone/common/sql/migrate_repo/versions/003_token_valid.py keystone/common/sql/migrate_repo/versions/004_undo_token_id_hash.py keystone/common/sql/migrate_repo/versions/005_set_utf8_character_set.py keystone/common/sql/migrate_repo/versions/006_add_policy_table.py keystone/common/sql/migrate_repo/versions/007_add_domain_tables.py keystone/common/sql/migrate_repo/versions/008_create_default_domain.py keystone/common/sql/migrate_repo/versions/009_normalize_identity.py keystone/common/sql/migrate_repo/versions/010_normalize_identity_migration.py keystone/common/sql/migrate_repo/versions/011_endpoints_v3.py keystone/common/sql/migrate_repo/versions/012_populate_endpoint_type.py keystone/common/sql/migrate_repo/versions/013_drop_legacy_endpoints.py keystone/common/sql/migrate_repo/versions/014_add_group_tables.py keystone/common/sql/migrate_repo/versions/015_tenant_to_project.py keystone/common/sql/migrate_repo/versions/016_normalize_domain_ids.py keystone/common/sql/migrate_repo/versions/017_membership_role.py keystone/common/sql/migrate_repo/versions/018_add_trust_tables.py keystone/common/sql/migrate_repo/versions/019_fixup_role.py keystone/common/sql/migrate_repo/versions/020_migrate_metadata_table_roles.py keystone/common/sql/migrate_repo/versions/021_add_trust_to_token.py keystone/common/sql/migrate_repo/versions/022_move_legacy_endpoint_id.py keystone/common/sql/migrate_repo/versions/023_drop_credential_constraints.py keystone/common/sql/migrate_repo/versions/024_add_index_to_expires.py keystone/common/sql/migrate_repo/versions/025_add_index_to_valid.py keystone/common/sql/migrate_repo/versions/026_drop_user_group_constraints.py keystone/common/sql/migrate_repo/versions/027_set_engine_mysql_innodb.py keystone/common/sql/migrate_repo/versions/028_fixup_group_metadata.py keystone/common/sql/migrate_repo/versions/029_update_assignment_metadata.py keystone/common/sql/migrate_repo/versions/030_drop_credential_constraint_sqlite.py keystone/common/sql/migrate_repo/versions/031_drop_credential_indexes.py keystone/common/sql/migrate_repo/versions/032_username_length.py keystone/common/sql/migrate_repo/versions/033_migrate_ec2credentials_table_credentials.py keystone/common/sql/migrate_repo/versions/034_add_default_project_id_column_to_user.py keystone/common/sql/migrate_repo/versions/035_add_compound_revoked_token_index.py keystone/common/sql/migrate_repo/versions/036_token_drop_valid_index.py keystone/common/sql/migrate_repo/versions/037_add_region_table.py keystone/common/sql/migrate_repo/versions/038_add_assignment_table.py keystone/common/sql/migrate_repo/versions/039_grant_to_assignment.py keystone/common/sql/migrate_repo/versions/040_drop_grant_tables.py keystone/common/sql/migrate_repo/versions/041_add_remaining_uses_count_to_trusts.py keystone/common/sql/migrate_repo/versions/042_endpoint_enabled.py keystone/common/sql/migrate_repo/versions/043_fixup_region_description.py keystone/common/sql/migrate_repo/versions/044_service_enabled.py keystone/common/sql/migrate_repo/versions/__init__.py keystone/contrib/__init__.py keystone/contrib/access/__init__.py keystone/contrib/access/core.py keystone/contrib/admin_crud/__init__.py keystone/contrib/admin_crud/core.py keystone/contrib/ec2/__init__.py keystone/contrib/ec2/controllers.py keystone/contrib/ec2/core.py keystone/contrib/ec2/routers.py keystone/contrib/endpoint_filter/__init__.py keystone/contrib/endpoint_filter/controllers.py keystone/contrib/endpoint_filter/core.py keystone/contrib/endpoint_filter/routers.py keystone/contrib/endpoint_filter/backends/__init__.py keystone/contrib/endpoint_filter/backends/catalog_sql.py keystone/contrib/endpoint_filter/backends/sql.py keystone/contrib/endpoint_filter/migrate_repo/__init__.py keystone/contrib/endpoint_filter/migrate_repo/migrate.cfg keystone/contrib/endpoint_filter/migrate_repo/versions/001_add_endpoint_filtering_table.py keystone/contrib/endpoint_filter/migrate_repo/versions/__init__.py keystone/contrib/example/__init__.py keystone/contrib/example/configuration.rst keystone/contrib/example/controllers.py keystone/contrib/example/core.py keystone/contrib/example/routers.py keystone/contrib/example/migrate_repo/__init__.py keystone/contrib/example/migrate_repo/migrate.cfg keystone/contrib/example/migrate_repo/versions/001_example_table.py keystone/contrib/example/migrate_repo/versions/__init__.py keystone/contrib/federation/__init__.py keystone/contrib/federation/controllers.py keystone/contrib/federation/core.py keystone/contrib/federation/routers.py keystone/contrib/federation/utils.py keystone/contrib/federation/backends/__init__.py keystone/contrib/federation/backends/sql.py keystone/contrib/federation/migrate_repo/__init__.py keystone/contrib/federation/migrate_repo/migrate.cfg keystone/contrib/federation/migrate_repo/versions/001_add_identity_provider_table.py keystone/contrib/federation/migrate_repo/versions/002_add_mapping_tables.py keystone/contrib/federation/migrate_repo/versions/__init__.py keystone/contrib/oauth1/__init__.py keystone/contrib/oauth1/controllers.py keystone/contrib/oauth1/core.py keystone/contrib/oauth1/routers.py keystone/contrib/oauth1/validator.py keystone/contrib/oauth1/backends/__init__.py keystone/contrib/oauth1/backends/sql.py keystone/contrib/oauth1/migrate_repo/__init__.py keystone/contrib/oauth1/migrate_repo/migrate.cfg keystone/contrib/oauth1/migrate_repo/versions/001_add_oauth_tables.py keystone/contrib/oauth1/migrate_repo/versions/002_fix_oauth_tables_fk.py keystone/contrib/oauth1/migrate_repo/versions/003_consumer_description_nullalbe.py keystone/contrib/oauth1/migrate_repo/versions/004_request_token_roles_nullable.py keystone/contrib/oauth1/migrate_repo/versions/__init__.py keystone/contrib/revoke/__init__.py keystone/contrib/revoke/controllers.py keystone/contrib/revoke/core.py keystone/contrib/revoke/model.py keystone/contrib/revoke/routers.py keystone/contrib/revoke/backends/__init__.py keystone/contrib/revoke/backends/kvs.py keystone/contrib/revoke/backends/sql.py keystone/contrib/revoke/migrate_repo/__init__.py keystone/contrib/revoke/migrate_repo/migrate.cfg keystone/contrib/revoke/migrate_repo/versions/001_revoke_table.py keystone/contrib/revoke/migrate_repo/versions/__init__.py keystone/contrib/s3/__init__.py keystone/contrib/s3/core.py keystone/contrib/simple_cert/__init__.py keystone/contrib/simple_cert/controllers.py keystone/contrib/simple_cert/core.py keystone/contrib/simple_cert/routers.py keystone/contrib/stats/__init__.py keystone/contrib/stats/core.py keystone/contrib/stats/backends/__init__.py keystone/contrib/stats/backends/kvs.py keystone/contrib/user_crud/__init__.py keystone/contrib/user_crud/core.py keystone/credential/__init__.py keystone/credential/controllers.py keystone/credential/core.py keystone/credential/routers.py keystone/credential/backends/__init__.py keystone/credential/backends/sql.py keystone/identity/__init__.py keystone/identity/controllers.py keystone/identity/core.py keystone/identity/routers.py keystone/identity/backends/__init__.py keystone/identity/backends/kvs.py keystone/identity/backends/ldap.py keystone/identity/backends/sql.py keystone/locale/keystone.pot keystone/locale/ar/LC_MESSAGES/keystone.po keystone/locale/bg_BG/LC_MESSAGES/keystone.po keystone/locale/bn_IN/LC_MESSAGES/keystone.po keystone/locale/bs/LC_MESSAGES/keystone.po keystone/locale/ca/LC_MESSAGES/keystone.po keystone/locale/cs/LC_MESSAGES/keystone.po keystone/locale/da/LC_MESSAGES/keystone.po keystone/locale/de/LC_MESSAGES/keystone.po keystone/locale/el/LC_MESSAGES/keystone.po keystone/locale/en_AU/LC_MESSAGES/keystone.po keystone/locale/en_GB/LC_MESSAGES/keystone.po keystone/locale/en_US/LC_MESSAGES/keystone.po keystone/locale/es/LC_MESSAGES/keystone.po keystone/locale/es_MX/LC_MESSAGES/keystone.po keystone/locale/eu/LC_MESSAGES/keystone.po keystone/locale/eu_ES/LC_MESSAGES/keystone.po keystone/locale/fa/LC_MESSAGES/keystone.po keystone/locale/fi_FI/LC_MESSAGES/keystone.po keystone/locale/fil/LC_MESSAGES/keystone.po keystone/locale/fr/LC_MESSAGES/keystone.po keystone/locale/gl/LC_MESSAGES/keystone.po keystone/locale/he/LC_MESSAGES/keystone.po keystone/locale/he_IL/LC_MESSAGES/keystone.po keystone/locale/hi/LC_MESSAGES/keystone.po keystone/locale/hr/LC_MESSAGES/keystone.po keystone/locale/hu/LC_MESSAGES/keystone.po keystone/locale/id/LC_MESSAGES/keystone.po keystone/locale/is_IS/LC_MESSAGES/keystone.po keystone/locale/it/LC_MESSAGES/keystone.po keystone/locale/it_IT/LC_MESSAGES/keystone.po keystone/locale/ja/LC_MESSAGES/keystone.po keystone/locale/ka_GE/LC_MESSAGES/keystone.po keystone/locale/km/LC_MESSAGES/keystone.po keystone/locale/kn/LC_MESSAGES/keystone.po keystone/locale/ko/LC_MESSAGES/keystone.po keystone/locale/ko_KR/LC_MESSAGES/keystone.po keystone/locale/ml_IN/LC_MESSAGES/keystone.po keystone/locale/mr_IN/LC_MESSAGES/keystone.po keystone/locale/ms/LC_MESSAGES/keystone.po keystone/locale/nb/LC_MESSAGES/keystone.po keystone/locale/ne/LC_MESSAGES/keystone.po keystone/locale/nl_NL/LC_MESSAGES/keystone.po keystone/locale/pa_IN/LC_MESSAGES/keystone.po keystone/locale/pl_PL/LC_MESSAGES/keystone.po keystone/locale/pt/LC_MESSAGES/keystone.po keystone/locale/pt_BR/LC_MESSAGES/keystone.po keystone/locale/ro/LC_MESSAGES/keystone.po keystone/locale/ru/LC_MESSAGES/keystone.po keystone/locale/ru_RU/LC_MESSAGES/keystone.po keystone/locale/sk/LC_MESSAGES/keystone.po keystone/locale/sl_SI/LC_MESSAGES/keystone.po keystone/locale/sq/LC_MESSAGES/keystone.po keystone/locale/sr/LC_MESSAGES/keystone.po keystone/locale/sv/LC_MESSAGES/keystone.po keystone/locale/sw_KE/LC_MESSAGES/keystone.po keystone/locale/ta/LC_MESSAGES/keystone.po keystone/locale/te_IN/LC_MESSAGES/keystone.po keystone/locale/tl/LC_MESSAGES/keystone.po keystone/locale/tl_PH/LC_MESSAGES/keystone.po keystone/locale/tr_TR/LC_MESSAGES/keystone.po keystone/locale/uk/LC_MESSAGES/keystone.po keystone/locale/ur/LC_MESSAGES/keystone.po keystone/locale/vi_VN/LC_MESSAGES/keystone.po keystone/locale/zh_CN/LC_MESSAGES/keystone.po keystone/locale/zh_HK/LC_MESSAGES/keystone.po keystone/locale/zh_TW/LC_MESSAGES/keystone.po keystone/middleware/__init__.py keystone/middleware/core.py keystone/middleware/ec2_token.py keystone/middleware/s3_token.py keystone/openstack/__init__.py keystone/openstack/common/README keystone/openstack/common/__init__.py keystone/openstack/common/context.py keystone/openstack/common/eventlet_backdoor.py keystone/openstack/common/exception.py keystone/openstack/common/excutils.py keystone/openstack/common/fileutils.py keystone/openstack/common/gettextutils.py keystone/openstack/common/importutils.py keystone/openstack/common/jsonutils.py keystone/openstack/common/local.py keystone/openstack/common/lockutils.py keystone/openstack/common/log.py keystone/openstack/common/loopingcall.py keystone/openstack/common/network_utils.py keystone/openstack/common/policy.py keystone/openstack/common/processutils.py keystone/openstack/common/service.py keystone/openstack/common/strutils.py keystone/openstack/common/test.py keystone/openstack/common/threadgroup.py keystone/openstack/common/timeutils.py keystone/openstack/common/uuidutils.py keystone/openstack/common/versionutils.py keystone/openstack/common/config/__init__.py keystone/openstack/common/config/generator.py keystone/openstack/common/db/__init__.py keystone/openstack/common/db/api.py keystone/openstack/common/db/exception.py keystone/openstack/common/db/options.py keystone/openstack/common/db/sqlalchemy/__init__.py keystone/openstack/common/db/sqlalchemy/migration.py keystone/openstack/common/db/sqlalchemy/models.py keystone/openstack/common/db/sqlalchemy/provision.py keystone/openstack/common/db/sqlalchemy/session.py keystone/openstack/common/db/sqlalchemy/test_base.py keystone/openstack/common/db/sqlalchemy/test_migrations.py keystone/openstack/common/db/sqlalchemy/utils.py keystone/openstack/common/fixture/__init__.py keystone/openstack/common/fixture/config.py keystone/openstack/common/fixture/lockutils.py keystone/openstack/common/fixture/mockpatch.py keystone/openstack/common/fixture/moxstubout.py keystone/openstack/common/py3kcompat/__init__.py keystone/openstack/common/py3kcompat/urlutils.py keystone/policy/__init__.py keystone/policy/controllers.py keystone/policy/core.py keystone/policy/routers.py keystone/policy/backends/__init__.py keystone/policy/backends/rules.py keystone/policy/backends/sql.py keystone/tests/__init__.py keystone/tests/core.py keystone/tests/default_catalog.templates keystone/tests/default_fixtures.py keystone/tests/fakeldap.py keystone/tests/filtering.py keystone/tests/mapping_fixtures.py keystone/tests/matchers.py keystone/tests/rest.py keystone/tests/test_associate_project_endpoint_extension.py keystone/tests/test_auth.py keystone/tests/test_auth_plugin.py keystone/tests/test_backend.py keystone/tests/test_backend_federation_sql.py keystone/tests/test_backend_kvs.py keystone/tests/test_backend_ldap.py keystone/tests/test_backend_rules.py keystone/tests/test_backend_sql.py keystone/tests/test_backend_templated.py keystone/tests/test_base64utils.py keystone/tests/test_cache.py keystone/tests/test_cache_backend_mongo.py keystone/tests/test_catalog.py keystone/tests/test_cert_setup.py keystone/tests/test_config.py keystone/tests/test_content_types.py keystone/tests/test_contrib_s3_core.py keystone/tests/test_contrib_simple_cert.py keystone/tests/test_contrib_stats_core.py keystone/tests/test_driver_hints.py keystone/tests/test_exception.py keystone/tests/test_injection.py keystone/tests/test_ipv6.py keystone/tests/test_keystoneclient.py keystone/tests/test_keystoneclient_sql.py keystone/tests/test_kvs.py keystone/tests/test_ldap_livetest.py keystone/tests/test_ldap_tls_livetest.py keystone/tests/test_matchers.py keystone/tests/test_middleware.py keystone/tests/test_no_admin_token_auth.py keystone/tests/test_notifications.py keystone/tests/test_pemutils.py keystone/tests/test_policy.py keystone/tests/test_revoke.py keystone/tests/test_s3_token_middleware.py keystone/tests/test_serializer.py keystone/tests/test_singular_plural.py keystone/tests/test_sizelimit.py keystone/tests/test_sql_livetest.py keystone/tests/test_sql_migrate_extensions.py keystone/tests/test_sql_upgrade.py keystone/tests/test_ssl.py keystone/tests/test_token_bind.py keystone/tests/test_token_provider.py keystone/tests/test_url_middleware.py keystone/tests/test_utils.py keystone/tests/test_v2_controller.py keystone/tests/test_v3.py keystone/tests/test_v3_auth.py keystone/tests/test_v3_catalog.py keystone/tests/test_v3_credential.py keystone/tests/test_v3_federation.py keystone/tests/test_v3_filters.py keystone/tests/test_v3_identity.py keystone/tests/test_v3_oauth1.py keystone/tests/test_v3_os_revoke.py keystone/tests/test_v3_policy.py keystone/tests/test_v3_protection.py keystone/tests/test_versions.py keystone/tests/test_wsgi.py keystone/tests/utils.py keystone/tests/config_files/backend_db2.conf keystone/tests/config_files/backend_ldap.conf keystone/tests/config_files/backend_ldap_sql.conf keystone/tests/config_files/backend_liveldap.conf keystone/tests/config_files/backend_multi_ldap_sql.conf keystone/tests/config_files/backend_mysql.conf keystone/tests/config_files/backend_postgresql.conf keystone/tests/config_files/backend_sql.conf keystone/tests/config_files/backend_tls_liveldap.conf keystone/tests/config_files/deprecated.conf keystone/tests/config_files/deprecated_override.conf keystone/tests/config_files/keystone.Default.conf keystone/tests/config_files/keystone.domain1.conf keystone/tests/config_files/keystone.domain2.conf keystone/tests/config_files/test_auth_plugin.conf keystone/tests/ksfixtures/__init__.py keystone/tests/ksfixtures/appserver.py keystone/tests/ksfixtures/cache.py keystone/tests/unit/__init__.py keystone/tests/unit/common/__init__.py keystone/tests/unit/common/test_sql_core.py keystone/tests/unit/common/test_utils.py keystone/tests/unit/identity/__init__.py keystone/tests/unit/identity/test_core.py keystone/token/__init__.py keystone/token/controllers.py keystone/token/core.py keystone/token/provider.py keystone/token/routers.py keystone/token/backends/__init__.py keystone/token/backends/kvs.py keystone/token/backends/memcache.py keystone/token/backends/sql.py keystone/token/providers/__init__.py keystone/token/providers/common.py keystone/token/providers/pki.py keystone/token/providers/uuid.py keystone/trust/__init__.py keystone/trust/controllers.py keystone/trust/core.py keystone/trust/routers.py keystone/trust/backends/__init__.py keystone/trust/backends/kvs.py keystone/trust/backends/sql.py tools/colorizer.py tools/convert_to_sqlite.sh tools/debug_helper.sh tools/install_venv.py tools/install_venv_common.py tools/sample_data.sh tools/with_venv.sh tools/config/README tools/config/check_uptodate.sh tools/config/generate_sample.sh tools/config/oslo.config.generator.rckeystone-2014.1/MANIFEST.in0000664000175400017540000000077312323716267016356 0ustar jenkinsjenkins00000000000000include AUTHORS include babel.cfg include ChangeLog include CONTRIBUTING.txt include LICENSE include HACKING.rst include README.rst include openstack-common.conf include run_tests.py include run_tests.sh include setup.cfg include setup.py include TODO include tox.ini include etc/* include httpd/* graft bin graft doc graft keystone/tests graft tools graft examples recursive-include keystone *.json *.xml *.cfg *.pem README *.po *.pot *.sql global-exclude *.pyc *.sdx *.log *.db *.swp keystone/tests/tmp/* keystone-2014.1/run_tests.sh0000775000175400017540000001101312323716267017172 0ustar jenkinsjenkins00000000000000#!/bin/bash # Copyright 2012 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. set -eu function usage { echo "Usage: $0 [OPTION]..." echo "Run Keystone's test suite(s)" echo "" echo " -V, --virtual-env Always use virtualenv. Install automatically if not present" echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment" echo " -x, --stop Stop running tests after the first error or failure." echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added." echo " -u, --update Update the virtual environment with any newer package versions" echo " -p, --pep8 Just run flake8" echo " -8, --8 Just run flake8, don't show PEP8 text for each error" echo " -P, --no-pep8 Don't run flake8" echo " -c, --coverage Generate coverage report" echo " -h, --help Print this usage message" echo "" echo "Note: with no options specified, the script will try to run the tests in a virtual environment," echo " If no virtualenv is found, the script will ask if you would like to create one. If you " echo " prefer to run tests NOT in a virtual environment, simply pass the -N option." exit } function process_option { case "$1" in -h|--help) usage;; -V|--virtual-env) always_venv=1; never_venv=0;; -N|--no-virtual-env) always_venv=0; never_venv=1;; -x|--stop) failfast=1;; -f|--force) force=1;; -u|--update) update=1;; -p|--pep8) just_flake8=1;; -8|--8) short_flake8=1;; -P|--no-pep8) no_flake8=1;; -c|--coverage) coverage=1;; -*) testropts="$testropts $1";; *) testrargs="$testrargs $1" esac } venv=.venv with_venv=tools/with_venv.sh always_venv=0 never_venv=0 force=0 failfast=0 testrargs= testropts=--subunit wrapper="" just_flake8=0 short_flake8=0 no_flake8=0 coverage=0 update=0 for arg in "$@"; do process_option $arg done TESTRTESTS="python setup.py testr" # If enabled, tell nose to collect coverage data if [ $coverage -eq 1 ]; then TESTRTESTS="$TESTRTESTS --coverage" fi function run_tests { set -e echo ${wrapper} if [ $failfast -eq 1 ]; then testrargs="$testrargs -- --failfast" fi ${wrapper} $TESTRTESTS --testr-args="$testropts $testrargs" | \ ${wrapper} subunit-2to1 | \ ${wrapper} tools/colorizer.py } function run_flake8 { FLAGS=--show-pep8 if [ $# -gt 0 ] && [ 'short' == ''$1 ] then FLAGS='' fi echo "Running flake8 ..." # Just run flake8 in current environment echo ${wrapper} flake8 $FLAGS | tee pep8.txt ${wrapper} flake8 $FLAGS | tee pep8.txt } if [ $never_venv -eq 0 ] then # Remove the virtual environment if --force used if [ $force -eq 1 ]; then echo "Cleaning virtualenv..." rm -rf ${venv} fi if [ $update -eq 1 ]; then echo "Updating virtualenv..." python tools/install_venv.py fi if [ -e ${venv} ]; then wrapper="${with_venv}" else if [ $always_venv -eq 1 ]; then # Automatically install the virtualenv python tools/install_venv.py wrapper="${with_venv}" else echo -e "No virtual environment found...create one? (Y/n) \c" read use_ve if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then # Install the virtualenv and run the test suite in it python tools/install_venv.py wrapper=${with_venv} fi fi fi fi # Delete old coverage data from previous runs if [ $coverage -eq 1 ]; then ${wrapper} coverage erase fi if [ $just_flake8 -eq 1 ]; then run_flake8 exit fi if [ $short_flake8 -eq 1 ]; then run_flake8 short exit fi run_tests # NOTE(sirp): we only want to run flake8 when we're running the full-test # suite, not when we're running tests individually. To handle this, we need to # distinguish between options (testropts), which begin with a '-', and arguments # (testrargs). if [ -z "$testrargs" ]; then if [ $no_flake8 -eq 0 ]; then run_flake8 fi fi keystone-2014.1/AUTHORS0000664000175400017540000000035612323716511015655 0ustar jenkinsjenkins00000000000000 Adam Young Hirofumi Ichihara Kanami Akama Luis A. Garcia Mathew Odden r-sekine keystone-2014.1/tox.ini0000664000175400017540000000231312323716272016117 0ustar jenkinsjenkins00000000000000[tox] minversion = 1.6 skipsdist = True envlist = py26,py27,py33,pep8,docs,sample_config [testenv] usedevelop = True install_command = pip install -U {opts} {packages} setenv = VIRTUAL_ENV={envdir} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = python setup.py testr --testr-args='{posargs}' [testenv:pep8] envdir = {toxworkdir}/venv commands = flake8 {posargs} [tox:jenkins] downloadcache = ~/cache/pip [testenv:cover] setenv = VIRTUAL_ENV={envdir} commands = python setup.py testr --coverage --testr-args='{posargs}' [testenv:venv] commands = {posargs} [testenv:debug] commands = {toxinidir}/tools/debug_helper.sh {posargs} [flake8] filename= *.py,keystone-* show-source = true # H803 Commit message should not end with a period (do not remove per list discussion) ignore = H803 builtins = _ exclude=.venv,.git,.tox,build,dist,doc,*openstack/common*,*lib/python*,*egg,tools,vendor,.update-venv,*.ini [testenv:docs] envdir = {toxworkdir}/venv commands= python setup.py build_sphinx [testenv:sample_config] envdir = {toxworkdir}/venv commands = {toxinidir}/tools/config/generate_sample.sh [hacking] import_exceptions = keystone.openstack.common.gettextutils._