Merge "Adds v2.0 files for api spec"
This commit is contained in:
commit
6c2559b574
|
@ -0,0 +1,20 @@
|
|||
===============================================
|
||||
OpenStack Identity API v2.0 Content compression
|
||||
===============================================
|
||||
|
||||
Request and response body data may be encoded with gzip compression in
|
||||
order to accelerate interactive performance of API calls and responses.
|
||||
This is controlled using the ``Accept-Encoding`` header on the request
|
||||
from the client and indicated by the ``Content-Encoding`` header in the
|
||||
server response. Unless the header is explicitly set, encoding defaults
|
||||
to disabled.
|
||||
|
||||
**Compression headers**
|
||||
|
||||
================= ================ =====
|
||||
Header type Name Value
|
||||
================= ================ =====
|
||||
HTTP/1.1 Request Accept-Encoding gzip
|
||||
HTTP/1.1 Response Content-Encoding gzip
|
||||
================= ================ =====
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
======================================
|
||||
OpenStack Identity API v2.0 Extensions
|
||||
======================================
|
||||
|
||||
The OpenStack Identity API is extensible. Extensions serve two purposes:
|
||||
They allow the introduction of new features in the API without requiring
|
||||
a version change and they allow the introduction of vendor specific
|
||||
niche functionality. Applications can programmatically determine what
|
||||
extensions are available by performing a **GET** on the /extensions URI.
|
||||
Note that this is a versioned request - that is, an extension available
|
||||
in one API version might not be available in another.
|
||||
|
||||
======= =========== ======================================
|
||||
Verb URI Description
|
||||
**GET** /extensions Returns a list of available extensions
|
||||
======= =========== ======================================
|
||||
|
||||
Normal response code(s):200, 203
|
||||
|
||||
Error response code(s): badRequest (400), identityFault (500),
|
||||
serviceUnavailable(503)
|
||||
|
||||
This operation does not require a request body.
|
||||
|
||||
Each extension is identified by two unique identifiers, a namespace and
|
||||
an alias. Additionally an extension contains documentation links in
|
||||
various formats.
|
||||
|
||||
**Example: List extensions: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extensions xmlns="http://docs.openstack.org/common/api/v1.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"/>
|
||||
|
||||
|
||||
**Example: List extensions: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"extensions": {
|
||||
"values": [
|
||||
{
|
||||
"updated": "2013-07-07T12:00:0-00:00",
|
||||
"name": "OpenStack S3 API",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/s3tokens/v1.0",
|
||||
"alias": "s3tokens",
|
||||
"description": "OpenStack S3 API."
|
||||
},
|
||||
{
|
||||
"updated": "2013-07-23T12:00:0-00:00",
|
||||
"name": "OpenStack Keystone Endpoint Filter API",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api/blob/master/openstack-identity-api/v3/src/markdown/identity-api-v3-os-ep-filter-ext.md",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/OS-EP-FILTER/v1.0",
|
||||
"alias": "OS-EP-FILTER",
|
||||
"description": "OpenStack Keystone Endpoint Filter API."
|
||||
},
|
||||
{
|
||||
"updated": "2013-12-17T12:00:0-00:00",
|
||||
"name": "OpenStack Federation APIs",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/OS-FEDERATION/v1.0",
|
||||
"alias": "OS-FEDERATION",
|
||||
"description": "OpenStack Identity Providers Mechanism."
|
||||
},
|
||||
{
|
||||
"updated": "2013-07-11T17:14:00-00:00",
|
||||
"name": "OpenStack Keystone Admin",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0",
|
||||
"alias": "OS-KSADM",
|
||||
"description": "OpenStack extensions to Keystone v2.0 API enabling Administrative Operations."
|
||||
},
|
||||
{
|
||||
"updated": "2014-01-20T12:00:0-00:00",
|
||||
"name": "OpenStack Simple Certificate API",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/OS-SIMPLE-CERT/v1.0",
|
||||
"alias": "OS-SIMPLE-CERT",
|
||||
"description": "OpenStack simple certificate retrieval extension"
|
||||
},
|
||||
{
|
||||
"updated": "2013-07-07T12:00:0-00:00",
|
||||
"name": "OpenStack EC2 API",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/OS-EC2/v1.0",
|
||||
"alias": "OS-EC2",
|
||||
"description": "OpenStack EC2 Credentials backend."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Extensions might also be queried individually by their unique alias.
|
||||
This provides the simplest method of checking if an extension is
|
||||
available as an unavailable extension issues an itemNotFound (404)
|
||||
response.
|
||||
|
||||
======= ======================= ====================================
|
||||
Verb URI Description
|
||||
**GET** /extensions/*``alias``* Return details of a single extension
|
||||
======= ======================= ====================================
|
||||
|
||||
Normal response code(s):200, 203
|
||||
|
||||
Error response code(s): itemNotFound (404), badRequest (400),
|
||||
identityFault (500), serviceUnavailable(503)
|
||||
|
||||
This operation does not require a request body.
|
||||
|
||||
**Example: Show extension details: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension xmlns="http://docs.openstack.org/common/api/v1.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
name="User Metadata Extension"
|
||||
namespace="http://docs.rackspacecloud.com/identity/api/ext/meta/v2.0"
|
||||
alias="RS-META" updated="2011-01-12T11:22:33-06:00">
|
||||
<description>Allows associating arbitrary metadata with a
|
||||
user.</description>
|
||||
<atom:link rel="describedby" type="application/pdf"
|
||||
href="http://docs.rackspacecloud.com/identity/api/ext/identity-meta-20111201.pdf"/>
|
||||
<atom:link rel="describedby" type="application/vnd.sun.wadl+xml"
|
||||
href="http://docs.rackspacecloud.com/identity/api/ext/identity-meta.wadl"
|
||||
/>
|
||||
</extension>
|
||||
|
||||
|
||||
**Example: Show extension details: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"extension": {
|
||||
"updated": "2013-07-07T12:00:0-00:00",
|
||||
"name": "OpenStack S3 API",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://github.com/openstack/identity-api",
|
||||
"type": "text/html",
|
||||
"rel": "describedby"
|
||||
}
|
||||
],
|
||||
"namespace": "http://docs.openstack.org/identity/api/ext/s3tokens/v1.0",
|
||||
"alias": "s3tokens",
|
||||
"description": "OpenStack S3 API."
|
||||
}
|
||||
}
|
||||
|
||||
Extensions can define new data types, parameters, actions, headers,
|
||||
states, and resources. In XML, additional elements and attributes might
|
||||
be defined. These elements must be defined in the extension's namespace.
|
||||
In JSON, the alias must be used. Extended headers are always
|
||||
prefixed with ``X-`` followed by the alias and a dash:
|
||||
(``X-RS-META-HEADER1``). Parameters must be prefixed with the extension
|
||||
alias followed by a colon.
|
||||
|
||||
.. note::
|
||||
|
||||
Applications should ignore response data that contains extension
|
||||
elements. Also, applications should also verify that an extension is
|
||||
available before submitting an extended request.
|
||||
|
||||
**Example: Show user details: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<user xmlns="http://docs.openstack.org/identity/api/v2.0" enabled="true"
|
||||
email="john.smith@example.org" id="u1000" username="jqsmith">
|
||||
<metadata xmlns="http://docs.rackspacecloud.com/identity/api/ext/meta/v2.0">
|
||||
<meta key="MetaKey1">MetaValue1</meta>
|
||||
<meta key="MetaKey2">MetaValue2</meta>
|
||||
</metadata>
|
||||
</user>
|
||||
|
||||
**Example: Show user details: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"user": {
|
||||
"id": "1000",
|
||||
"username": "jqsmith",
|
||||
"email": "john.smith@example.org",
|
||||
"enabled": true,
|
||||
"RS-META:metadata": {
|
||||
"values": {
|
||||
"MetaKey1": "MetaValue1",
|
||||
"MetaKey2": "MetaValue2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
==================================
|
||||
OpenStack Identity API v2.0 Faults
|
||||
==================================
|
||||
|
||||
When an error occurs, the system returns an HTTP error response code
|
||||
denoting the type of error. The system also returns additional
|
||||
information about the fault in the body of the response.
|
||||
|
||||
**Example: Identity fault: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<identityFault xmlns="http://docs.openstack.org/identity/api/v2.0" code="500">
|
||||
<message>Fault</message>
|
||||
<details>Error Details...</details>
|
||||
</identityFault>
|
||||
|
||||
|
||||
**Example: Identity fault: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"identityFault": {
|
||||
"message": "Fault",
|
||||
"details": "Error Details...",
|
||||
"code": 500
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
The response body returns the error code for convenience. The message
|
||||
section returns a human readable message. The details section is
|
||||
optional and might contain useful information for tracking down an error
|
||||
(such as, a stack trace).
|
||||
|
||||
The root element of the fault (for example, identityFault) might change
|
||||
depending on the type of error. The following is an example of an
|
||||
itemNotFound error.
|
||||
|
||||
**Example: itemNotFound fault: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itemNotFound xmlns="http://docs.openstack.org/identity/api/v2.0"
|
||||
code="404">
|
||||
<message>Item not found.</message>
|
||||
<details>Error Details...</details>
|
||||
</itemNotFound>
|
||||
|
||||
|
||||
**Example: itemNotFound fault: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"itemNotFound": {
|
||||
"message": "Item not found.",
|
||||
"details": "Error Details...",
|
||||
"code": 404
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
The following table shows the possible fault types with associated error
|
||||
codes:
|
||||
|
||||
**Table: Fault types**
|
||||
|
||||
=================== ===================== ========================
|
||||
Fault element Associated error code Expected in all requests
|
||||
|
||||
identityFault 500, 400 Yes
|
||||
serviceUnavailable 503 Yes
|
||||
badRequest 400 Yes
|
||||
unauthorized 401 Yes
|
||||
overLimit 413 No
|
||||
userDisabled 403 No
|
||||
forbidden 403 No
|
||||
itemNotFound 404 No
|
||||
tenantConflict 409 No
|
||||
=================== ===================== ========================
|
||||
|
||||
|
||||
From an XML schema perspective, all API faults are extensions of the
|
||||
base identityFault fault type. When working with a system that binds XML
|
||||
to actual classes (such as JAXB), one should be capable of using
|
||||
identityFault as a catch-all if there's no interest in distinguishing
|
||||
between individual fault types.
|
|
@ -0,0 +1,214 @@
|
|||
=================================================
|
||||
OpenStack Identity API v2.0 Paginated collections
|
||||
=================================================
|
||||
|
||||
To reduce load on the service, list operations return a maximum number
|
||||
of items at a time. The maximum number of items returned is determined
|
||||
by the Identity provider. To navigate the collection, you can set the
|
||||
*``limit``* and *``marker``* parameters in the URI. For example,
|
||||
?\ *``limit``*\ =100&\ *``marker``*\ =1234. The *``marker``* parameter
|
||||
is the ID of the last item in the previous list. Items are sorted by
|
||||
update time. When an update time is not available they are sorted by ID.
|
||||
The *``limit``* parameter sets the page size. Both parameters are
|
||||
optional. If the client requests a *``limit``* beyond that which is
|
||||
supported by the deployment an overLimit (413) fault might be thrown. A
|
||||
marker with an invalid ID returns an itemNotFound (404) fault.
|
||||
|
||||
.. note::
|
||||
|
||||
Paginated collections never return itemNotFound (404) faults when the
|
||||
collection is empty - clients should expect an empty collection.
|
||||
|
||||
For convenience, collections contain atom "next" and "previous" links.
|
||||
The first page in the list does not contain a ``previous`` link, the
|
||||
last page in the list does not contain a ``next`` link. The following
|
||||
examples illustrate three pages in a collection of tenants. The first
|
||||
page was retrieved through a **GET** to
|
||||
``http://identity.api.openstack.org/v2.0/1234/tenants?limit=1``. In
|
||||
these examples, the *``limit``* parameter sets the page size to a single
|
||||
item. Subsequent ``next`` and ``previous`` links honor the initial page
|
||||
size. Thus, a client might follow links to traverse a paginated
|
||||
collection without having to input the *``marker``* parameter.
|
||||
|
||||
**Example: Tenant collection, first page: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tenants xmlns="http://docs.openstack.org/identity/api/v2.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<tenant enabled="true" id="1234" name="ACME Corp">
|
||||
<description>A description...</description>
|
||||
</tenant>
|
||||
<atom:link
|
||||
rel="next"
|
||||
href="http://identity.api.openstack.org/v2.0/tenants?limit=1&marker=1234"/>
|
||||
</tenants>
|
||||
|
||||
|
||||
|
||||
**Example: Tenant collection, first page: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"tenants": [
|
||||
{
|
||||
"id": "1234",
|
||||
"name": "ACME corp",
|
||||
"description": "A description ...",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"tenants_links": [
|
||||
{
|
||||
"rel": "next",
|
||||
"href": "http://identity.api.openstack.org/v2.0/tenants?limit=1&marker=1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
**Example: Tenant collection, second page: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tenants xmlns="http://docs.openstack.org/identity/api/v2.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<tenant enabled="true" id="3645" name="Iron Works">
|
||||
<description>A description...</description>
|
||||
</tenant>
|
||||
<atom:link
|
||||
rel="previous"
|
||||
href="http://identity.api.openstack.org/v2.0/tenants?limit=1"/>
|
||||
<atom:link
|
||||
rel="next"
|
||||
href="http://identity.api.openstack.org/v2.0/tenants?limit=1&marker=3645"/>
|
||||
</tenants>
|
||||
|
||||
|
||||
|
||||
**Example: Tenant collection, second page: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"tenants": [
|
||||
{
|
||||
"id": "3645",
|
||||
"name": "Iron Works",
|
||||
"description": "A description ...",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"tenants_links": [
|
||||
{
|
||||
"rel": "next",
|
||||
"href": "http://identity.api.openstack.org/v2.0/tenants?limit=1&marker=3645"
|
||||
},
|
||||
{
|
||||
"rel": "previous",
|
||||
"href": "http://identity.api.openstack.org/v2.0/tenants?limit=1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
**Example: Tenant collection, last page: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tenants xmlns="http://docs.openstack.org/identity/api/v2.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<tenant enabled="true" id="9999" name="Bigz">
|
||||
<description>A description...</description>
|
||||
</tenant>
|
||||
<atom:link
|
||||
rel="previous"
|
||||
href="http://identity.api.openstack.org/v2.0/tenants?limit=1&marker=1234"/>
|
||||
</tenants>
|
||||
|
||||
|
||||
|
||||
**Example: Tenant collection, last page: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"tenants": [
|
||||
{
|
||||
"id": "9999",
|
||||
"name": "Bigz",
|
||||
"description": "A description ...",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"tenants_links": [
|
||||
{
|
||||
"rel": "previous",
|
||||
"href": "http://identity.api.openstack.org/v2.0/tenants?limit=1&marker=1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
In the JSON representation, paginated collections contain a values
|
||||
property that contains the items in the collections. Links are accessed
|
||||
via the links property. The approach allows for extensibility of both
|
||||
the collection members and of the paginated collection itself. It also
|
||||
allows collections to be embedded in other objects as illustrated below.
|
||||
Here, a subset of groups are presented within a user. Clients must
|
||||
follow the "next" link to continue to retrieve additional groups
|
||||
belonging to a user.
|
||||
|
||||
**Example: Paginated roles in user: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<user xmlns="http://docs.openstack.org/identity/api/v2.0" xmlns:atom="http://www.w3.org/2005/Atom"
|
||||
enabled="true" email="john.smith@example.org" username="jqsmith" id="u1000">
|
||||
<roles xmlns="http://docs.openstack.org/identity/api/ext/role">
|
||||
<role tenantId="1234" id="Admin"/>
|
||||
<role tenantId="1234" id="DBUser"/>
|
||||
<atom:link rel="next"
|
||||
href="http://identity.api.openstack.org/v2.0/tenants/1234/users/u1000/groups?marker=Super"
|
||||
/>
|
||||
</roles>
|
||||
</user>
|
||||
|
||||
|
||||
|
||||
**Example: Paginated roles in user: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"user": {
|
||||
"OS-ROLE:roles": [
|
||||
{
|
||||
"tenantId": "1234",
|
||||
"id": "Admin"
|
||||
},
|
||||
{
|
||||
"tenantId": "1234",
|
||||
"id": "DBUser"
|
||||
}
|
||||
],
|
||||
"OS-ROLE:roles_links": [
|
||||
{
|
||||
"rel": "next",
|
||||
"href": "http://identity.api.openstack.org/v2.0/tenants/1234/users/u1000/roles?marker=Super"
|
||||
}
|
||||
],
|
||||
"id": "u1000",
|
||||
"username": "jqsmith",
|
||||
"email": "john.smith@example.org",
|
||||
"enabled": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
========================================================
|
||||
OpenStack Identity API v2.0 Request and response formats
|
||||
========================================================
|
||||
|
||||
The OpenStack Identity API supports both JSON and XML data serialization
|
||||
request and response formats.
|
||||
|
||||
Use the ``Content-Type`` request header to specify the request format.
|
||||
This header is required for operations that have a request body.
|
||||
|
||||
The syntax for the ``Content-Type`` header is:
|
||||
|
||||
.. code::
|
||||
|
||||
Content-Type: application/FORMAT
|
||||
|
||||
Where *``FORMAT``* is either ``json`` or ``xml``.
|
||||
|
||||
Use one of the following methods to specify the response format:
|
||||
|
||||
``Accept`` header
|
||||
The syntax for the ``Accept`` header is:
|
||||
|
||||
.. code::
|
||||
|
||||
Accept: application/FORMAT
|
||||
|
||||
Where *``FORMAT``* is either ``json`` or ``xml``. The default format
|
||||
is ``json``.
|
||||
|
||||
Query extension
|
||||
Add an ``.xml`` or ``.json`` extension to the request URI. For
|
||||
example, the ``.xml`` extension in the following list servers URI
|
||||
request specifies that the response body is to be returned in XML
|
||||
format:
|
||||
|
||||
.. code::
|
||||
|
||||
GET publicURL/servers.xml
|
||||
|
||||
If you do not specify a response format, JSON is the default.
|
||||
|
||||
If the ``Accept`` header and the query extension specify conflicting
|
||||
formats, the format specified in the query extension takes precedence.
|
||||
For example, if the query extension is ``.xml`` and the ``Accept``
|
||||
header specifies ``application/json``, the response is returned in XML
|
||||
format.
|
||||
|
||||
You can serialize a response in a different format from the request
|
||||
format. Here are some examples.
|
||||
|
||||
**Example: Request with headers: JSON**
|
||||
|
||||
.. code::
|
||||
|
||||
POST /v2.0/tokens HTTP/1.1
|
||||
Host: identity.api.openstack.org
|
||||
Content-Type: application/json
|
||||
Accept: application/xml
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"auth": {
|
||||
"tenantName": "demo",
|
||||
"passwordCredentials": {
|
||||
"username": "demo",
|
||||
"password": "devstack"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
**Example: Response with headers: XML**
|
||||
|
||||
.. code::
|
||||
|
||||
HTTP/1.1 200 OKAY
|
||||
Date: Mon, 12 Nov 2010 15:55:01 GMT
|
||||
Content-Length:
|
||||
Content-Type: application/xml; charset=UTF-8
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<access xmlns="http://docs.openstack.org/identity/api/v2.0">
|
||||
<token issued_at="2014-01-30T15:49:11.054709"
|
||||
expires="2014-01-31T15:49:11Z"
|
||||
id="aaaaa-bbbbb-ccccc-dddd">
|
||||
<tenant enabled="true" name="demo"
|
||||
id="fc394f2ab2df4114bde39905f800dc57"/>
|
||||
</token>
|
||||
<serviceCatalog>
|
||||
<service type="compute" name="nova">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:8774/v2/fc394f2ab2df4114bde39905f800dc57"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:8774/v2/fc394f2ab2df4114bde39905f800dc57"
|
||||
internalURL="http://23.253.72.207:8774/v2/fc394f2ab2df4114bde39905f800dc57"
|
||||
id="2dad48f09e2a447a9bf852bcd93548ef"
|
||||
/>
|
||||
</service>
|
||||
<service type="network" name="neutron">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:9696/"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:9696/"
|
||||
internalURL="http://23.253.72.207:9696/"
|
||||
id="97c526db8d7a4c88bbb8d68db1bdcdb8"
|
||||
/>
|
||||
</service>
|
||||
<service type="volumev2" name="cinder">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:8776/v2/fc394f2ab2df4114bde39905f800dc57"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:8776/v2/fc394f2ab2df4114bde39905f800dc57"
|
||||
internalURL="http://23.253.72.207:8776/v2/fc394f2ab2df4114bde39905f800dc57"
|
||||
id="93f86dfcbba143a39a33d0c2cd424870"
|
||||
/>
|
||||
</service>
|
||||
<service type="computev3" name="nova">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:8774/v3"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:8774/v3"
|
||||
internalURL="http://23.253.72.207:8774/v3"
|
||||
id="3eb274b12b1d47b2abc536038d87339e"
|
||||
/>
|
||||
</service>
|
||||
<service type="s3" name="s3">
|
||||
<endpoints_links/>
|
||||
<endpoint adminURL="http://23.253.72.207:3333"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:3333"
|
||||
internalURL="http://23.253.72.207:3333"
|
||||
id="957f1e54afc64d33a62099faa5e980a2"
|
||||
/>
|
||||
</service>
|
||||
<service type="image" name="glance">
|
||||
<endpoints_links/>
|
||||
<endpoint adminURL="http://23.253.72.207:9292"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:9292"
|
||||
internalURL="http://23.253.72.207:9292"
|
||||
id="27d5749f36864c7d96bebf84a5ec9767"
|
||||
/>
|
||||
</service>
|
||||
<service type="volume" name="cinder">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:8776/v1/fc394f2ab2df4114bde39905f800dc57"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:8776/v1/fc394f2ab2df4114bde39905f800dc57"
|
||||
internalURL="http://23.253.72.207:8776/v1/fc394f2ab2df4114bde39905f800dc57"
|
||||
id="37c83a2157f944f1972e74658aa0b139"
|
||||
/>
|
||||
</service>
|
||||
<service type="ec2" name="ec2">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:8773/services/Admin"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:8773/services/Cloud"
|
||||
internalURL="http://23.253.72.207:8773/services/Cloud"
|
||||
id="289b59289d6048e2912b327e5d3240ca"
|
||||
/>
|
||||
</service>
|
||||
<service type="object-store" name="swift">
|
||||
<endpoints_links/>
|
||||
<endpoint adminURL="http://23.253.72.207:8080"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:8080/v1/AUTH_fc394f2ab2df4114bde39905f800dc57"
|
||||
internalURL="http://23.253.72.207:8080/v1/AUTH_fc394f2ab2df4114bde39905f800dc57"
|
||||
id="16b76b5e5b7d48039a6e4cc3129545f3"
|
||||
/>
|
||||
</service>
|
||||
<service type="identity" name="keystone">
|
||||
<endpoints_links/>
|
||||
<endpoint
|
||||
adminURL="http://23.253.72.207:35357/v2.0"
|
||||
region="RegionOne"
|
||||
publicURL="http://23.253.72.207:5000/v2.0"
|
||||
internalURL="http://23.253.72.207:5000/v2.0"
|
||||
id="26af053673df4ef3a2340c4239e21ea2"
|
||||
/>
|
||||
</service>
|
||||
</serviceCatalog>
|
||||
<user username="demo" id="9a6590b2ab024747bc2167c4e064d00d"
|
||||
name="demo">
|
||||
<roles_links/>
|
||||
<role name="Member"/>
|
||||
<role name="anotherrole"/>
|
||||
</user>
|
||||
<metadata is_admin="0">
|
||||
<roles>
|
||||
<role>7598ac3c634d4c3da4b9126a5f67ca2b</role>
|
||||
<role>f95c0ab82d6045d9805033ee1fbc80d4</role>
|
||||
</roles>
|
||||
</metadata>
|
||||
</access>
|
|
@ -0,0 +1,364 @@
|
|||
====================================
|
||||
OpenStack Identity API v2.0 Versions
|
||||
====================================
|
||||
|
||||
The OpenStack Identity API uses both a URI and a MIME type versioning
|
||||
scheme. In the URI scheme, the first element of the path contains the
|
||||
target version identifier (for example,
|
||||
https://identity.api.openstack.org/ v2.0/). The MIME type versioning
|
||||
scheme uses HTTP content negotiation where the ``Accept`` or
|
||||
``Content-Type`` headers contains a MIME type that includes the version
|
||||
ID as a parameter (application/vnd.openstack.identity+xml;version=1.1).
|
||||
A version MIME type is always linked to a base MIME type
|
||||
(application/xml or application/json). If conflicting versions are
|
||||
specified using both an HTTP header and a URI, the URI takes precedence.
|
||||
|
||||
**Example: Request with MIME type versioning**
|
||||
|
||||
.. code::
|
||||
|
||||
GET /tenants HTTP/1.1
|
||||
Host: identity.api.openstack.org
|
||||
Accept: application/vnd.openstack.identity+xml;version=1.1
|
||||
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
|
||||
|
||||
|
||||
**Example: Request with URI versioning**
|
||||
|
||||
.. code::
|
||||
|
||||
GET /v1.1/tenants HTTP/1.1
|
||||
Host: identity.api.openstack.org
|
||||
Accept: application/xml
|
||||
X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
The MIME type versioning approach allows for the creation of permanent
|
||||
links, because the version scheme is not specified in the URI path:
|
||||
``https://api.identity.openstack.org/tenants/12234``.
|
||||
|
||||
If a request is made without a version specified in the URI or through
|
||||
HTTP headers, a multiple-choices response (300) provides links and MIME
|
||||
types to available versions.
|
||||
|
||||
**Example: Multiple choices: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<choices xmlns="http://docs.openstack.org/common/api/v1.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<version id="v1.0" status="DEPRECATED">
|
||||
<media-types>
|
||||
<media-type base="application/xml"
|
||||
type="application/vnd.openstack.identity+xml;version=1.0"/>
|
||||
<media-type base="application/json"
|
||||
type="application/vnd.openstack.identity+json;version=1.0"/>
|
||||
</media-types>
|
||||
<atom:link rel="self" href="http://identity.api.openstack.org/v1.0"/>
|
||||
</version>
|
||||
<version id="v1.1" status="CURRENT">
|
||||
<media-types>
|
||||
<media-type base="application/xml"
|
||||
type="application/vnd.openstack.identity+xml;version=1.1"/>
|
||||
<media-type base="application/json"
|
||||
type="application/vnd.openstack.identity+json;version=1.1"/>
|
||||
</media-types>
|
||||
<atom:link rel="self" href="http://identity.api.openstack.org/v1.1"/>
|
||||
</version>
|
||||
<version id="v2.0" status="BETA">
|
||||
<media-types>
|
||||
<media-type base="application/xml"
|
||||
type="application/vnd.openstack.identity+xml;version=2.0"/>
|
||||
<media-type base="application/json"
|
||||
type="application/vnd.openstack.identity+json;version=2.0"/>
|
||||
</media-types>
|
||||
<atom:link rel="self" href="http://identity.api.openstack.org/v2.0"/>
|
||||
</version>
|
||||
</choices>
|
||||
|
||||
**Example: Multiple choices: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"choices": [
|
||||
{
|
||||
"id": "v1.0",
|
||||
"status": "DEPRECATED",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://identity.api.openstack.org/v1.0"
|
||||
}
|
||||
],
|
||||
"media-types": {
|
||||
"values": [
|
||||
{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.identity+xml;version=1.0"
|
||||
},
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.identity+json;version=1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "v1.1",
|
||||
"status": "CURRENT",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://identity.api.openstack.org/v1.1"
|
||||
}
|
||||
],
|
||||
"media-types": {
|
||||
"values": [
|
||||
{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.identity+xml;version=1.1"
|
||||
},
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.identity+json;version=1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "v2.0",
|
||||
"status": "BETA",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://identity.api.openstack.org/v2.0"
|
||||
}
|
||||
],
|
||||
"media-types": {
|
||||
"values": [
|
||||
{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.identity+xml;version=2.0"
|
||||
},
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.identity+json;version=2.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"choices_links": ""
|
||||
}
|
||||
|
||||
|
||||
New features and functionality that do not break API-compatibility are
|
||||
introduced in the current version of the API as extensions (see the
|
||||
following section) and the URI and MIME types remain unchanged. Features
|
||||
or functionality changes that would necessitate a break in
|
||||
API-compatibility require a new version, which results in URI and MIME
|
||||
type versions being updated accordingly. When new API versions are
|
||||
released, older versions are marked as ``DEPRECATED``. Providers should
|
||||
work with developers and partners to ensure adequate migration time to
|
||||
the new version before deprecated versions are discontinued.
|
||||
|
||||
Your application can programmatically determine available API versions
|
||||
by performing a **GET** on the root URL (such as, with the version and
|
||||
everything to the right of it truncated) returned from the
|
||||
authentication system. Note that an Atom representation of the versions
|
||||
resources is supported when issuing a request with the ``Accept`` header
|
||||
containing application/atom+xml or by adding a .atom to the request URI.
|
||||
This enables standard Atom clients to track version changes.
|
||||
|
||||
**Example: List versions: HTTP request**
|
||||
|
||||
.. code::
|
||||
|
||||
GET HTTP/1.1
|
||||
Host: identity.api.openstack.org
|
||||
|
||||
|
||||
|
||||
Normal response code(s):200, 203
|
||||
|
||||
Error response code(s): badRequest (400), identityFault (500),
|
||||
serviceUnavailable(503)
|
||||
|
||||
This operation does not require a request body.
|
||||
|
||||
**Example: List versions: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<versions xmlns="http://docs.openstack.org/common/api/v1.0"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
|
||||
<version id="v1.0" status="DEPRECATED"
|
||||
updated="2009-10-09T11:30:00Z">
|
||||
<atom:link rel="self"
|
||||
href="http://identity.api.openstack.org/v1.0/"/>
|
||||
</version>
|
||||
|
||||
<version id="v1.1" status="CURRENT"
|
||||
updated="2010-12-12T18:30:02.25Z">
|
||||
<atom:link rel="self"
|
||||
href="http://identity.api.openstack.org/v1.1/"/>
|
||||
</version>
|
||||
|
||||
<version id="v2.0" status="BETA"
|
||||
updated="2011-05-27T20:22:02.25Z">
|
||||
<atom:link rel="self"
|
||||
href="http://identity.api.openstack.org/v2.0/"/>
|
||||
</version>
|
||||
|
||||
</versions>
|
||||
|
||||
|
||||
|
||||
**Example: List versions: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"id": "v1.0",
|
||||
"status": "DEPRECATED",
|
||||
"updated": "2009-10-09T11:30:00Z",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://identity.api.openstack.org/v1.0/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "v1.1",
|
||||
"status": "CURRENT",
|
||||
"updated": "2010-12-12T18:30:02.25Z",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://identity.api.openstack.org/v1.1/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "v2.0",
|
||||
"status": "BETA",
|
||||
"updated": "2011-05-27T20:22:02.25Z",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://identity.api.openstack.org/v2.0/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"versions_links": []
|
||||
}
|
||||
|
||||
|
||||
|
||||
You can also obtain additional information about a specific version by
|
||||
performing a **GET** on the base version URL (for example,
|
||||
https://identity.api.openstack.org/v2.0/). Version request URLs should
|
||||
always end with a trailing slash (/). If the slash is omitted, the
|
||||
server might respond with a 302 redirection request. Format extensions
|
||||
might be placed after the slash (for example,
|
||||
https://identity.api.openstack.org/v2.0/.xml). Note that this is a
|
||||
special case that does not hold true for other API requests. In general,
|
||||
requests such as /tenants.xml and /tenants/.xml are handled
|
||||
equivalently.
|
||||
|
||||
**Example: Get version details: HTTP request**
|
||||
|
||||
.. code::
|
||||
|
||||
GET HTTP/1.1
|
||||
Host: identity.api.openstack.org/v2.0/
|
||||
|
||||
|
||||
Normal response code(s):200, 203
|
||||
|
||||
Error response code(s): badRequest (400), identityFault (500),
|
||||
serviceUnavailable(503)
|
||||
|
||||
This operation does not require a request body.
|
||||
|
||||
**Example: Get version details: XML response**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<version xmlns="http://docs.openstack.org/identity/api/v2.0"
|
||||
status="stable" updated="2013-03-06T00:00:00Z" id="v2.0">
|
||||
<media-types>
|
||||
<media-type base="application/json"
|
||||
type="application/vnd.openstack.identity-v2.0+json"/>
|
||||
<media-type base="application/xml"
|
||||
type="application/vnd.openstack.identity-v2.0+xml"/>
|
||||
</media-types>
|
||||
<links>
|
||||
<link href="http://localhost:5000/v2.0/" rel="self"/>
|
||||
<link
|
||||
href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/"
|
||||
type="text/html" rel="describedby"/>
|
||||
<link
|
||||
href="http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf"
|
||||
type="application/pdf" rel="describedby"/>
|
||||
</links>
|
||||
</version>
|
||||
|
||||
|
||||
**Example: Get version details: JSON response**
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
{
|
||||
"version": {
|
||||
"status": "stable",
|
||||
"updated": "2014-04-17T00:00:00Z",
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.identity-v2.0+json"
|
||||
},
|
||||
{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.identity-v2.0+xml"
|
||||
}
|
||||
],
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://23.253.228.211: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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. annegentle: Removed paragraph and note about machine readable link and WADL
|
||||
because there's nothing machine readable on docs.openstack.org/api/ after we
|
||||
get these specs here. Need to investigate this -- is it sufficient to
|
||||
redirect:
|
||||
http://docs.openstack.org/api/openstack-identity-service/2.0/content/
|
||||
to
|
||||
http://specs.openstack.org/?
|
|
@ -0,0 +1,105 @@
|
|||
====================================
|
||||
OpenStack Identity API v2.0 overview
|
||||
====================================
|
||||
|
||||
The OpenStack Identity API is implemented using a RESTful web service
|
||||
interface. All requests to authenticate and operate against the
|
||||
OpenStack Identity API should be performed using SSL over HTTP (HTTPS)
|
||||
on TCP port 443.
|
||||
|
||||
OpenStack Identity enables clients to obtain tokens that permit access
|
||||
OpenStack cloud services.
|
||||
|
||||
Intended audience
|
||||
-----------------
|
||||
|
||||
This reference is for software developers who develop applications that
|
||||
use the Identity API for authentication.
|
||||
|
||||
This reference assumes that the reader is familiar with RESTful web
|
||||
services, HTTP/1.1, and JSON or XML serialization formats.
|
||||
|
||||
Identity concepts
|
||||
-----------------
|
||||
|
||||
To use OpenStack Identity, you must be familiar with these key concepts:
|
||||
|
||||
**User**
|
||||
A digital representation of a person, system, or service that uses
|
||||
OpenStack cloud services. OpenStack Identity authentication services
|
||||
validate that an incoming request is being made by the user who
|
||||
claims to be making the call.
|
||||
|
||||
Users have a login and may be assigned tokens to access resources.
|
||||
Users may be directly assigned to a particular tenant and behave as
|
||||
if they are contained in that tenant.
|
||||
|
||||
**Credentials**
|
||||
Data that belongs to, is owned by, and generally only known by a
|
||||
user that the user can present to prove their identity.
|
||||
|
||||
Examples include:
|
||||
|
||||
- A matching username and password
|
||||
|
||||
- A matching username and API key
|
||||
|
||||
- A token that was issued to you
|
||||
|
||||
**Authentication**
|
||||
In the context OpenStack Identity, the act of confirming the
|
||||
identity of a user or the truth of a claim. OpenStack Identity
|
||||
confirms that an incoming request is being made by the user who
|
||||
claims to be making the call by validating a set of claims that the
|
||||
user is making.
|
||||
|
||||
These claims are initially in the form of a set of credentials
|
||||
(username & password, or username and API key). After initial
|
||||
confirmation, OpenStack Identity issues the user a token, which the
|
||||
user can then provide to demonstrate that their identity has been
|
||||
authenticated when making subsequent requests.
|
||||
|
||||
**Token**
|
||||
An arbitrary bit of text that is used to access resources. Each
|
||||
token has a scope that describes which resources are accessible with
|
||||
it. A token may be revoked at anytime and is valid for a finite
|
||||
duration.
|
||||
|
||||
While OpenStack Identity supports token-based authentication in this
|
||||
release, the intention is for it to support additional protocols in
|
||||
the future. The intent is for it to be an integration service
|
||||
foremost, and not aspire to be a full-fledged identity store and
|
||||
management solution.
|
||||
|
||||
**Tenant**
|
||||
A container used to group or isolate resources and/or identity
|
||||
objects. Depending on the service operator, a tenant can map to a
|
||||
customer, account, organization, or project.
|
||||
|
||||
**Service**
|
||||
An OpenStack service, such as Compute (Nova), Object Storage
|
||||
(Swift), or Image Service (Glance). A service provides one or more
|
||||
endpoints through which users can access resources and perform
|
||||
operations.
|
||||
|
||||
**Endpoint**
|
||||
A network-accessible address, usually described by a URL, where a
|
||||
service may be accessed. If using an extension for templates, you
|
||||
can create an endpoint template, which represents the templates of
|
||||
all the consumable services that are available across the regions.
|
||||
|
||||
**Role**
|
||||
A personality that a user assumes when performing a specific set of
|
||||
operations. A role includes a set of rights and privileges. A user
|
||||
assuming that role inherits those rights and privileges.
|
||||
|
||||
In OpenStack Identity, a token that is issued to a user includes the
|
||||
list of roles that user can assume. Services that are being called
|
||||
by that user determine how they interpret the set of roles a user
|
||||
has and to which operations or resources each role grants access.
|
||||
|
||||
It is up to individual services such as the Compute service and
|
||||
Image service to assign meaning to these roles. As far as the
|
||||
Identity service is concerned, a role is an arbitrary name assigned
|
||||
by the user.
|
||||
|
|
@ -10,18 +10,16 @@ Identity v3 API
|
|||
|
||||
api/v3/*
|
||||
|
||||
.. NOTE(dhellmann): Uncomment this section after there is at least one
|
||||
non-template spec for keystoneclient.
|
||||
|
||||
=================
|
||||
Identity v2.0 API
|
||||
=================
|
||||
=================
|
||||
Identity v2.0 API
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
|
||||
api/v2.0/*
|
||||
api/v2.0/*
|
||||
|
||||
|
||||
================================
|
||||
|
|
Loading…
Reference in New Issue