Moves identity admin into admin-guide-cloud separate from compute

Fixes typo.
Ensures keystone logging is documented.

Closes-bug: 1111092
Closes-bug: 1227890

Change-Id: I0a392d69c77ad1207868dc29341c8fd92d0a9836
This commit is contained in:
annegentle 2013-09-19 16:33:30 -05:00 committed by Andreas Jaeger
parent b2b654464e
commit 62cb8a9442
8 changed files with 498 additions and 134 deletions

View File

@ -75,6 +75,7 @@
</info>
<!-- Chapters are referred from the book file through these include statements. You can add additional chapters using these types of statements. -->
<xi:include href="../common/ch_getstart.xml"/>
<xi:include href="ch_identity_mgmt.xml"/>
<xi:include href="ch_dashboard.xml"/>
<xi:include href="ch_compute.xml"/>
<xi:include href="ch_objectstorage.xml"/>

View File

@ -334,138 +334,53 @@
</simplesect>
</section>
</section>
<section xml:id="section_identity-mgmt">
<title>Identity management</title>
<para>The Identity Service, code-named Keystone, is the default identity service for OpenStack.
After you install the Identity Service, you configure it through the
<filename>etc/keystone.conf</filename> configuration file, the PasteDeploy
<filename>etc/keystone-paste.ini</filename> configuration file, and possibly a
separate logging configuration file. You use the keystone command-line client to
initialize data into the Identity Service.</para>
<xi:include href="../common/section_keystone-concepts.xml"/>
<section xml:id="section_memcached-and-system-time">
<title>Memcached and system time</title>
<para>If you use <link xlink:href="http://memcached.org/">memcached</link> with the Identity Service&#x2014;for example, using the
memcache token driver or the <literal>auth_token</literal>
middleware&#x2014;ensure that the system time of memcached
hosts is set to UTC. Memcached uses the host's system time in
determining whether a key has expired, whereas the Identity Service sets key
expiry in UTC. The timezone used by the Identity Service and memcached must
match if key expiry is to behave as expected.</para>
</section>
<section xml:id="section_user-crud">
<title>User CRUD</title>
<para>The Identity Service 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
<literal>user_crud_extension</literal> filter, insert it after
the <literal>*_body</literal> middleware and before the
<literal>public_service</literal> app in the public_api WSGI
pipeline in <filename>keystone-paste.ini</filename>. For example:</para>
<programlisting language="ini">[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</programlisting>
<para>Each user can change their own password with a HTTP PATCH,
as follows:</para>
<screen><prompt>$</prompt> <userinput>curl -X PATCH http://localhost:5000/v2.0/OS-KSCRUD/users/&lt;userid&gt; -H &quot;Content-type: application/json&quot; \
-H &quot;X_Auth_Token: &lt;authtokenid&gt;&quot; -d '{&quot;user&quot;: {&quot;password&quot;: &quot;ABCD&quot;, &quot;original_password&quot;: &quot;DCBA&quot;}}'</userinput></screen>
<para>If the backend is kvs or sql, all users' passwords are
changed and their tokens are deleted.</para>
</section>
<section xml:id="section_monitoring">
<title>Monitoring</title>
<para>The Identity Service provides some basic request/response monitoring
statistics.</para>
<para>To enable data collection, define a
<literal>stats_monitoring</literal> filter and include it at
the beginning of any desired WSGI pipelines in
<filename>keystone-paste.ini</filename>, as follows:</para>
<programlisting language="ini">[filter:stats_monitoring]
paste.filter_factory = keystone.contrib.stats:StatsMiddleware.factory
[pipeline:public_api]
pipeline = stats_monitoring [...] public_service</programlisting>
<para>To enable reporting of collected data, define a
<literal>stats_reporting</literal> filter and include it near
the end of your <literal>admin_api</literal> WSGI pipeline after
<literal>*_body</literal> middleware and before
<literal>*_extension</literal> filters, as follows:</para>
<programlisting language="ini">[filter:stats_reporting]
paste.filter_factory = keystone.contrib.stats:StatsExtension.factory
[pipeline:admin_api]
pipeline = [...] json_body stats_reporting ec2_extension [...] admin_service</programlisting>
<para>Query the admin API for statistics, as follows:</para>
<screen><prompt>$</prompt> <userinput>curl -H 'X-Auth-Token: ADMIN' http://localhost:35357/v2.0/OS-STATS/stats</userinput></screen>
<para>Reset collected data, as follows:</para>
<screen><prompt>$</prompt> <userinput>curl -H 'X-Auth-Token: ADMIN' -X DELETE http://localhost:35357/v2.0/OS-STATS/stats</userinput></screen>
</section>
<xi:include href="../common/section_keystone_certificates-for-pki.xml"/>
<section xml:id="section_running-keystone">
<title>Run the Identity Service</title>
<para>To start the Identity Service, run the following
command:</para>
<screen><prompt>$</prompt> <userinput>keystone-all</userinput></screen>
<para>This command starts two wsgi.Server instances, configured by
the <filename>keystone.conf</filename> and
<filename>keystone-paste.ini</filename> configuration file.
One of these wsgi 'servers' is <literal>admin</literal> (the
administration API) and the other is <literal>main</literal>
(the primary/public API interface). Both of these run in a
single process.</para>
</section>
<xi:include href="../common/section_identity-troubleshooting.xml"/>
</section>
<section xml:id="section_image-mgmt">
<title>Image management</title>
<para>The OpenStack Image Service, code-named <emphasis role="italic">glance</emphasis>,
discovers, registers, and retrieves virtual machine images.
The service includes a <link
xlink:href="http://api.openstack.org/api-ref.html#os-images-2.0">RESTful API</link> that
allows users to query VM image metadata and retrieve the actual image with HTTP requests.
You can also use the <link
xlink:href="http://docs.openstack.org/cli/quick-start/content/glance_client.html">glance
command-line tool</link>, or the <link
xlink:href="http://docs.openstack.org/developer/python-glanceclient/">Python API</link>
to accomplish the same tasks.</para>
<para>VM images made available through OpenStack Image Service can be stored in a variety of
locations. The OpenStack Image Service supports the following backend stores:</para>
<itemizedlist>
<listitem>
<para>OpenStack Object Storage - OpenStack Object Storage (code-named <emphasis
<title>Image management</title>
<para>The OpenStack Image Service, code-named <emphasis role="italic">glance</emphasis>,
discovers, registers, and retrieves virtual machine images.
The service includes a <link
xlink:href="http://api.openstack.org/api-ref.html#os-images-2.0">RESTful API</link> that
allows users to query VM image metadata and retrieve the actual image with HTTP requests.
You can also use the <link
xlink:href="http://docs.openstack.org/cli/quick-start/content/glance_client.html">glance
command-line tool</link>, or the <link
xlink:href="http://docs.openstack.org/developer/python-glanceclient/">Python API</link>
to accomplish the same tasks.</para>
<para>VM images made available through OpenStack Image Service can be stored in a variety of
locations. The OpenStack Image Service supports the following backend stores:</para>
<itemizedlist>
<listitem>
<para>OpenStack Object Storage - OpenStack Object Storage (code-named <emphasis
role="italic">swift</emphasis>) is the highly-available object storage project
in OpenStack.</para>
</listitem>
<listitem>
<para>Filesystem - The default backend that OpenStack
Image Service uses to store virtual machine images is
the filesystem backend. This simple backend writes
image files to the local filesystem.</para>
</listitem>
<listitem>
<para>S3 - This backend allows OpenStack Image Service to
store virtual machine images in Amazons S3
service.</para>
</listitem>
<listitem>
<para>HTTP - OpenStack Image Service can read virtual
machine images that are available through HTTP somewhere
on the Internet. This store is read only.</para>
</listitem>
<listitem>
<para>Rados Block Device (RBD) - This backend stores images inside of a Ceph storage
cluster using Ceph's RBD interface.</para>
</listitem>
<listitem>
<para>GridFS - This backend stores images inside of MongoDB.</para>
</listitem>
</itemizedlist>
<para>You must have a working installation of the Image Service, with a working
endpoint and users created in the Identity Service. Also, you must source the environment
variables required by the nova and glance clients.</para>
in OpenStack.</para>
</listitem>
<listitem>
<para>Filesystem - The default backend that OpenStack
Image Service uses to store virtual machine images is
the filesystem backend. This simple backend writes
image files to the local filesystem.</para>
</listitem>
<listitem>
<para>S3 - This backend allows OpenStack Image Service to
store virtual machine images in Amazons S3
service.</para>
</listitem>
<listitem>
<para>HTTP - OpenStack Image Service can read virtual
machine images that are available through HTTP somewhere
on the Internet. This store is read only.</para>
</listitem>
<listitem>
<para>Rados Block Device (RBD) - This backend stores images inside of a Ceph storage
cluster using Ceph's RBD interface.</para>
</listitem>
<listitem>
<para>GridFS - This backend stores images inside of MongoDB.</para>
</listitem>
</itemizedlist>
<para>You must have a working installation of the Image Service, with a working
endpoint and users created in the Identity Service. Also, you must source the environment
variables required by the nova and glance clients.</para>
</section>
<section xml:id="section_instance-mgmt">
<title>Instance management</title>

View File

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
xml:id="ch-identity-mgmt-config">
<title>Identity Management</title>
<para>
The default identity management system for OpenStack is the OpenStack Identity Service, code-named Keystone.
Once Identity is installed, it is configured via a primary
configuration file (<filename>etc/keystone.conf</filename>), possibly
a separate logging configuration file, and initializing data into
keystone using the command line client.
</para>
<xi:include href="../common/section_keystone-concepts.xml"/>
<section xml:id="user-crud">
<title>User CRUD</title>
<para>
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 <literal>user_crud_extension</literal> filter, insert it after
the <literal>*_body</literal> middleware and before the
<literal>public_service</literal> app in the public_api WSGI
pipeline in <filename>keystone.conf</filename> e.g.:
</para>
<programlisting language="ini">
[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
</programlisting>
<para>
Each user can then change their own password with a HTTP PATCH
</para>
<programlisting language="ini">
&gt; curl -X PATCH http://localhost:5000/v2.0/OS-KSCRUD/users/&lt;userid&gt; -H &quot;Content-type: application/json&quot; \
-H &quot;X_Auth_Token: &lt;authtokenid&gt;&quot; -d '{&quot;user&quot;: {&quot;password&quot;: &quot;ABCD&quot;, &quot;original_password&quot;: &quot;DCBA&quot;}}'
</programlisting>
<para>
In addition to changing their password all of the users current
tokens will be deleted (if the backend used is kvs or sql)
</para>
</section>
<section xml:id="keystone-logging">
<title>Logging</title>
<para> Logging is configured externally to the rest of Identity,
the file specifying the logging configuration is in the
<literal>[DEFAULT]</literal> section of the
<filename>keystone.conf</filename> file under
<literal>log_config</literal>. If you wish to route all your
logging through syslog, set <literal>use_syslog=true</literal>
option in the <literal>[DEFAULT]</literal> section. </para>
<para>
A sample logging file is available with the project in the
directory <filename>etc/logging.conf.sample</filename>. Like other
OpenStack projects, Identity uses the `python logging module`,
which includes extensive configuration options for choosing the
output levels and formats.
</para>
<para>
In addition to this documentation page, you can check the
<filename>etc/keystone.conf</filename> sample configuration files
distributed with keystone for example configuration files for each
server application.
</para>
<para>For services which have separate paste-deploy ini file,
auth_token middleware can be alternatively configured in
[keystone_authtoken] section in the main config file, such as
<filename>nova.conf</filename>. For
example in Nova, all middleware parameters can be removed from
api-paste.ini like these:</para>
<programlisting language="ini"> [filter:authtoken]
paste.filter_factory =
keystoneclient.middleware.auth_token:filter_factory
</programlisting>
<para>and set in
<filename>nova.conf</filename> like these: </para>
<programlisting language="ini">[DEFAULT]
...
auth_strategy=keystone
[keystone_authtoken]
auth_host = 127.0.0.1
auth_port = 35357
auth_protocol = http
auth_uri = http://127.0.0.1:5000/
admin_user = admin
admin_password = SuperSekretPassword
admin_tenant_name = service
</programlisting>
<para>Note that middleware parameters in
paste config take priority, they must be removed to use values
in [keystone_authtoken] section.</para>
</section>
<section xml:id="monitoring">
<title>Monitoring</title>
<para>
Keystone provides some basic request/response monitoring
statistics out of the box.
</para>
<para>
Enable data collection by defining a
<literal>stats_monitoring</literal> filter and including it at the
beginning of any desired WSGI pipelines:
</para>
<programlisting language="ini">
[filter:stats_monitoring]
paste.filter_factory = keystone.contrib.stats:StatsMiddleware.factory
[pipeline:public_api]
pipeline = stats_monitoring [...] public_service
</programlisting>
<para>
Enable the reporting of collected data by defining a
<literal>stats_reporting</literal> filter and including it near
the end of your <literal>admin_api</literal> WSGI pipeline (After
<literal>*_body</literal> middleware and before
<literal>*_extension</literal> filters is recommended):
</para>
<programlisting language="ini">
[filter:stats_reporting]
paste.filter_factory = keystone.contrib.stats:StatsExtension.factory
[pipeline:admin_api]
pipeline = [...] json_body stats_reporting ec2_extension [...] admin_service
</programlisting>
<para>
Query the admin API for statistics using:
</para>
<screen><prompt>$</prompt> <userinput>curl -H 'X-Auth-Token: ADMIN' http://localhost:35357/v2.0/OS-STATS/stats</userinput></screen>
<para>
Reset collected data using:
</para>
<screen><prompt>$</prompt> <userinput>curl -H 'X-Auth-Token: ADMIN' -X DELETE http://localhost:35357/v2.0/OS-STATS/stats</userinput></screen>
</section>
<section xml:id="running-keystone">
<title>Running</title>
<para>
Running Identity is simply starting the services by using the
command:
</para>
<screen><prompt>$</prompt> <userinput>
keystone-all
</userinput></screen>
<para>
Invoking this command starts up two wsgi.Server instances,
configured by the <filename>keystone.conf</filename> file as
described above. One of these wsgi 'servers' is
<literal>admin</literal> (the administration API) and the other is
<literal>main</literal> (the primary/public API interface). Both
of these run in a single process.
</para>
</section>
<section xml:id="example-usage">
<title>Example usage</title>
<para>The <literal>keystone</literal> client is set up to expect commands
in the general form of <literal>keystone</literal>
<literal>command</literal>
<literal>argument</literal>, followed by flag-like keyword arguments to
provide additional (often optional) information. For example, the
command <literal>user-list</literal> and
<literal>tenant-create</literal> can be invoked as follows: </para>
<programlisting language="bash">
# Using token auth env variables
export SERVICE_ENDPOINT=http://127.0.0.1:5000/v2.0/
export SERVICE_TOKEN=secrete_token
keystone user-list
keystone tenant-create --name=demo
# Using token auth flags
keystone --token=secrete --endpoint=http://127.0.0.1:5000/v2.0/ user-list
keystone --token=secrete --endpoint=http://127.0.0.1:5000/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 --username=admin --password=secrete --tenant_name=admin user-list
keystone --username=admin --password=secrete --tenant_name=admin tenant-create --name=demo
</programlisting>
</section>
<section xml:id="auth-token-middleware-with-username-and-password">
<title>Auth-Token Middleware with Username and Password</title>
<para>
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.
</para>
<para>
Here is an example paste config filter that makes use of the
'admin_user' and 'admin_password' parameters:
</para>
<screen>
[filter:authtoken]
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
service_port = 5000
service_host = 127.0.0.1
auth_port = 35357
auth_host = 127.0.0.1
auth_token = 012345SECRET99TOKEN012345
admin_user = admin
admin_password = keystone123
</screen>
<para>
It should be noted that when using this option an admin
tenant/role relationship is required. The admin user is granted
access to the 'Admin' role on the 'admin' tenant.
</para>
</section>
<xi:include href="../common/section_identity-troubleshooting.xml"/>
</chapter>

View File

@ -426,7 +426,7 @@
</listitem>
</itemizedlist></para>
</section>
<section xml:id="services">
<section xml:id="networking-services">
<title>Place services on physical hosts</title>
<para>Like other OpenStack services, Networking provides
cloud administrators with significant flexibility in
@ -453,7 +453,7 @@
the <literal>neutron-l3-agent</literal> and other
OpenStack services.</para>
</section>
<section xml:id="connectivity">
<section xml:id="network-connectivity">
<title>Network connectivity for physical hosts</title>
<mediaobject>
<imageobject>

View File

@ -69,7 +69,8 @@ provides a service catalog within a particular OpenStack cloud.</td>
<tr>
<td><link xlink:href="http://www.openstack.org/software/openstack-shared-services/">Image
Service</link></td>
<td><link xlink:href="http://docs.openstack.org/developer/glance/">Glance</link>.</td>
<td><link xlink:href="http://docs.openstack.org/developer/glance/"
>Glance</link></td>
<td>Provides a registry of virtual machine images. Compute Service
uses it to provision instances.
</td>

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<section
xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
xml:id="configuring-keystone-for-ldap-backend">
<title>Configuring OpenStack Identity for an LDAP backend</title>
<para> As an alternative to the SQL Database backing store, Identity can use
a directory server to provide the Identity service. An example schema
for AcmeExample would look like this: </para>
<screen>
dn: dc=AcmeExample,dc=org
dc: AcmeExample
objectClass: dcObject
objectClass: organizationalUnit
ou: AcmeExample
dn: ou=Groups,dc=AcmeExample,dc=org
objectClass: top
objectClass: organizationalUnit
ou: groups
dn: ou=Users,dc=AcmeExample,dc=org
objectClass: top
objectClass: organizationalUnit
ou: users
dn: ou=Roles,dc=AcmeExample,dc=org
objectClass: top
objectClass: organizationalUnit
ou: roles
</screen>
<para> The corresponding entries in the <filename>keystone.conf</filename>
configuration file are:</para>
<programlisting language="ini">
[ldap]
url = ldap://localhost
user = dc=Manager,dc=AcmeExample,dc=org
password = badpassword
suffix = dc=AcmeExample,dc=org
use_dumb_member = False
allow_subtree_delete = False
user_tree_dn = ou=Users,dc=AcmeExample,dc=com
user_objectclass = inetOrgPerson
tenant_tree_dn = ou=Groups,dc=AcmeExample,dc=com
tenant_objectclass = groupOfNames
role_tree_dn = ou=Roles,dc=AcmeExample,dc=com
role_objectclass = organizationalRole
</programlisting>
<para>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
<emphasis>uid</emphasis> field should probably be
<emphasis>uidNumber</emphasis> and <emphasis>username</emphasis>
field either <emphasis>uid</emphasis> or <emphasis>cn</emphasis>. To
change these two fields, the corresponding entries in the Keystone
configuration file are: </para>
<programlisting language="ini">
[ldap]
user_id_attribute = uidNumber
user_name_attribute = cn
</programlisting>
<para>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: </para>
<programlisting language="ini">
[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
</programlisting>
<para>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: </para>
<programlisting language="ini">
[ldap]
user_filter = (memberof=CN=acme-users,OU=workgroups,DC=AcmeExample,DC=com)
tenant_filter =
role_filter =
</programlisting>
<para>
In case that the directory server does not have an attribute enabled
of type boolean for the user, there are several configuration
parameters that can be used to extract the value from an integer
attribute like in Active Directory:
</para>
<programlisting language="ini">
[ldap]
user_enabled_attribute = userAccountControl
user_enabled_mask = 2
user_enabled_default = 512
</programlisting>
<para>
In this case the attribute is an integer and the enabled attribute
is listed in bit 1, so the if the mask configured
<emphasis>user_enabled_mask</emphasis> is different from 0, it gets
the value from the field <emphasis>user_enabled_attribute</emphasis>
and it makes an ADD operation with the value indicated on
<emphasis>user_enabled_mask</emphasis> and if the value matches the
mask then the account is disabled.
</para>
<para>
It also saves the value without mask to the user identity in the
attribute <emphasis>enabled_nomask</emphasis>. 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
<emphasis>user_enabled_mask</emphasis> is needed in order to create
a default value on the integer attribute (512 = NORMAL ACCOUNT on
AD)
</para>
<para>
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 so:
</para>
<programlisting language="ini">
[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 =
</programlisting>
</section>

View File

@ -13,5 +13,7 @@
<xi:include href="../common/section_identity-configure.xml"/>
<xi:include href="../common/section_keystone_certificates-for-pki.xml"/>
<xi:include href="../common/section_keystone-ssl-config.xml"/>
<xi:include href="../common/section_keystone-external-auth.xml"/>
<xi:include href="../common/section_config_keystone_ldap.xml"/>
<xi:include href="../common/section_keystone-sample-conf-files.xml"/>
</chapter>

View File

@ -30,8 +30,78 @@
<para>Before you can run keystone client commands, you must
download and source an OpenStack RC file. See <xref
linkend="cli_openrc"/>.</para>
<section xml:id="services">
<title>Services</title>
<para>To look at your service catalog, use these keystone client commands.</para>
<section xml:id="keystone-service-create">
<title><literal>service-create</literal></title>
<para>Keyword arguments:</para>
<itemizedlist>
<listitem>
<para>Name</para>
</listitem>
<listitem>
<para>Type</para>
</listitem>
<listitem>
<para>Description</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<screen><prompt>$</prompt> <userinput>
keystone service create \
--name=nova \
--type=compute \
--description=&quot;Nova Compute Service&quot;</userinput>
</screen>
</section>
<section xml:id="keystone-service-list">
<title><literal>service-list</literal></title>
<para>Arguments</para>
<itemizedlist>
<listitem>
<para>service_id</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<screen>
keystone service-list
</screen>
</section>
<section xml:id="keystone-service-get">
<title><literal>service-get</literal></title>
<para>Arguments</para>
<itemizedlist>
<listitem>
<para>service_id</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<screen><prompt>$</prompt> <userinput>
keystone service-get 08741d8ed88242ca88d1f61484a0fe3b</userinput>
</screen>
</section>
<section xml:id="keystone-service-delete">
<title><literal>service-delete</literal></title>
<para>Arguments</para>
<itemizedlist>
<listitem>
<para>service_id</para>
</listitem>
</itemizedlist>
<para>Example:</para>
<screen><prompt>$</prompt> <userinput>
keystone service-delete 08741d8ed88242ca88d1f61484a0fe3b</userinput>
</screen>
</section>
<section xml:id="admin_cli_projects">
<title>Create a project</title>
<title>Create a tenant (project)</title>
<para>A tenant is a group of zero or more users. In nova, a
tenant owns virtual machines. In swift, a tenant owns
containers. In the Dashboard, tenants are represented as projects.
Users can be associated with more than one tenant.
Each tenant and user pairing can have a role associated with
it.</para>
<procedure>
<step>
<para>To list all projects with their ID, name, and
@ -309,4 +379,5 @@
</step>
</procedure>
</section>
</section>
</section>