Adding tutorial for OpenStack Shade library

Fixed also a bunch of English-language to the getting started text

co-authored-by: Diane Fleming

Change-Id: I9318cdefb628a7441a984f7c8f200202b41430dd
This commit is contained in:
Stefano Maffulli 2015-07-20 12:47:30 -07:00
parent d94389b445
commit c5fa73302b
6 changed files with 434 additions and 52 deletions

View File

@ -1,52 +1,46 @@
========================================
Writing your first OpenStack application
Writing Your First OpenStack Application
========================================
This tutorial works with the `First App Application for OpenStack <https://github.com/stackforge/faafo/>`_.
This directory contains the "Writing Your First OpenStack Application"
tutorial.
The tutorials work with an application that can be found at
`https://github.com/stackforge/faafo <https://github.com/stackforge/faafo/>`_.
Prerequisites
=============
-------------
To build the documentation, install `Python Tox <https://tox.readthedocs.org/>`_.
To install Tox for Ubuntu 14.04 and later::
apt-get install python-tox python-dev libxml2-dev libxslt1-dev
Structure
=========
To build the documentation, you must install the Graphviz package.
/source
~~~~~~~
The :code:`/source` directory contains the tutorial documentation as
`reStructuredText <http://docutils.sourceforge.net/rst.html>`_ (RST). The
documentation is built with `Sphinx <http://sphinx-doc.org/>`_.
`reStructuredText <http://docutils.sourceforge.net/rst.html>`_ (RST).
The RST source includes conditional output logic. To invoke
:code:`sphinx-build` with :code:`-t libcloud`::
To build the documentation, you must install `Sphinx <http://sphinx-doc.org/>`_ and the
`OpenStack docs.openstack.org Sphinx theme (openstackdocstheme) <https://pypi.python.org/pypi/openstackdocstheme/>`_. When
you invoke tox, these dependencies are automatically pulled in from the
top-level :code:`test-requirements.txt`.
You must also install `Graphviz <http://www.graphviz.org/>`_ on your build system.
The RST source includes conditional output logic. The following command
invokes :code:`sphinx-build` with :code:`-t libcloud`::
tox -e firstapp-libcloud
Only the sections marked :code:`.. only:: libcloud` in the RST are built.
To build the documentation, you must install `Sphinx <http://sphinx-doc.org/>`_
and the
`OpenStack docs.openstack.org Sphinx theme (openstackdocstheme) <https://pypi.python.org/pypi/openstackdocstheme>`_.
When you invoke tox, these dependencies are automatically pulled in from the
top-level :code:`test-requirements.txt`.
You must also install `Graphviz <http://www.graphviz.org/>`_ on your build system.
/samples
~~~~~~~~
The code samples in the guide are located in this directory. The code samples
The code samples in this guide are located in this directory. The code samples
for each SDK are located in separate subdirectories.
/build-libcloud
~~~~~~~~~~~~~~~
The HTML documentation is built in this directory. This directory is included
in the project :code:`.gitignore`.
The HTML documentation is built in this directory. The :code:`.gitignore` file
for the project specifies this directory.

View File

@ -0,0 +1,8 @@
clouds:
myfavoriteopenstack:
auth:
auth_url: https://controller:5000/
username: $YOUR_USERNAME
password: $YOUR_PASSWORD
project_name: $YOUR_PROJECT
region_name: $REGION

View File

@ -0,0 +1,94 @@
#step-1
from shade import *
simple_logging(debug=True)
conn = openstack_cloud(cloud='myfavoriteopenstack')
#step-2
images = conn.list_images()
for image in images:
print(image)
#step-3
flavors = conn.list_flavors()
for flavor in flavors:
print(flavor)
#step-4
image_id = 'c55094e9-699c-4da9-95b4-2e2e75f4c66e'
image = conn.get_image(image_id)
print(image)
#step-5
flavor_id = 'subsonic'
flavor = conn.get_flavor(flavor_id)
print(flavor)
#step-6
instance_name = 'testing'
testing_instance = conn.create_server(wait=True, auto_ip=True,
name=instance_name,
image=image_id,
flavor=flavor_id)
print(testing_instance)
#step-7
instances = conn.list_servers()
for instance in instances:
print(instance)
#step-8
conn.delete_server(name=instance_name)
#step-9
print('Checking for existing SSH keypair...')
keypair_name = 'demokey'
pub_key_file = '~/.ssh/demo_key.pub'
if conn.search_keypairs(keypair_name):
print('Keypair already exists. Skipping import.')
else:
print('Adding keypair...')
conn.create_keypair(keypair_name, open(pub_key_file, 'r').read().strip())
for keypair in conn.list_keypairs():
print(keypair)
#step-10
print('Checking for existing security groups...')
sec_group_name = 'all-in-one'
if conn.search_security_groups(sec_group_name):
print('Security group already exists. Skipping creation.')
else:
print('Creating security group.')
conn.create_security_group(sec_group_name, 'network access for all-in-one application.')
conn.create_security_group_rule(sec_group_name, 80, 80, 'TCP')
conn.create_security_group_rule(sec_group_name, 22, 22, 'TCP')
conn.search_security_groups(sec_group_name)
#step-11
ex_userdata = '''#!/usr/bin/env bash
curl -L -s https://git.openstack.org/cgit/stackforge/faafo/plain/contrib/install.sh | bash -s -- \
-i faafo -i messaging -r api -r worker -r demo
'''
#step-12
instance_name = 'all-in-one'
testing_instance = conn.create_server(wait=True, auto_ip=False,
name=instance_name,
image=image_id,
flavor=flavor_id,
key_name=keypair_name,
security_groups=[sec_group_name],
userdata=ex_userdata)
#step-13
f_ip = conn.available_floating_ip()
#step-14
conn.attach_ip_to_server(testing_instance['id'], f_ip['id'])
#step-15
print('The Fractals app will be deployed to http://%s' % f_ip['floating_ip_address'] )

View File

@ -27,9 +27,9 @@ A general overview
This tutorial shows two applications. The first application is a simple
fractal generator that uses mathematical equations to generate beautiful
`fractal images <http://en.wikipedia.org/wiki/Fractal>`_ . We show
you this application in its entirety so that you can compare it to the second,
more robust, application.
`fractal images <http://en.wikipedia.org/wiki/Fractal>`_ . We show you this
application in its entirety so that you can compare it to a second, more
robust, application.
The second application is an OpenStack application that enables you to:
@ -56,6 +56,8 @@ Language Name Description
Python Libcloud A Python-based library managed by the Apache Foundation.
This library enables you to work with multiple types of clouds. https://libcloud.apache.org
Python OpenStack SDK A Python-based library specifically developed for OpenStack. https://github.com/stackforge/python-openstacksdk
Python Shade A Python-based library developed by OpenStack Infra team to https://github.com/openstack-infra/shade
operate multiple OpenStack clouds.
Java jClouds A Java-based library. Like Libcloud, it's also managed by the https://jclouds.apache.org
Apache Foundation and works with multiple types of clouds.
Ruby fog A Ruby-based SDK for multiple clouds. https://github.com/fog/fog/blob/master/lib/fog/openstack/docs/getting_started.md
@ -147,8 +149,13 @@ To interact with the cloud, you must also have
This document has not yet been completed for the php-opencloud SDK.
You need the following information that you can obtain from your cloud
provider:
.. only:: shade
`a recent version of shade library installed <https://pypi.python.org/pypi/shade/0.11.0>`_.
.. note:: Before proceeding, install the latest version of shade.
Obtain the following information from your cloud provider:
* auth URL
* user name
@ -156,29 +163,28 @@ provider:
* project ID or name (projects are also known as tenants)
* cloud region
You can also download the OpenStack RC file from the OpenStack dashboard. Log
in to the Horizon dashboard and click :guilabel:`Project->Access &
Security->API Access->Download OpenStack RC file`. If you choose this route,
be aware that the "auth URL" doesn't include the path. For example, if your
You can also download the OpenStack RC file from the OpenStack Horizon
dashboard. Log in to the dashboard and click :guilabel:`Project->Access &
Security->API Access->Download OpenStack RC file`. If you use this method, be
aware that the "auth URL" does not include the path. For example, if your
:file:`openrc.sh` file shows:
.. code-block:: bash
export OS_AUTH_URL=http://controller:5000/v2.0
the actual auth URL will be
The actual auth URL is:
.. code-block:: python
http://controller:5000
How you'll interact with OpenStack
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this tutorial, you interact with your OpenStack cloud through one of the
SDKs you have chosen in "Choose your OpenStack SDK." This guide assumes you
are familiar with running code snippets in your language of choice.
In this tutorial, you interact with your OpenStack cloud through the SDK that
you chose in "Choose your OpenStack SDK." This guide assumes that you know how
to run code snippets in your language of choice.
.. only:: fog
@ -242,12 +248,30 @@ are familiar with running code snippets in your language of choice.
.. note:: If you receive the
:code:`libcloud.common.types.InvalidCredsError: 'Invalid
credentials with the provider'` exception while trying to run
one of the following API calls, double-check your credentials.
credentials with the provider'` exception when you run
one of these API calls, double-check your credentials.
.. note:: If your provider does not support regions, try a
blank string ('') for the `region_name`.
.. only:: shade
Use your credentials above to specify the cloud provider name,
user name, password, project_name and region_name in the file
:file:`~/.config/openstack/clouds.yml`.
.. literalinclude:: ../samples/shade/clouds.yml
:language: yaml
.. note:: If you do use a public cloud `known by shade
<http://git.openstack.org/cgit/openstack/os-client-config/tree/os_client_config/vendors>`_,
you can avoid specifying :code:`auth_url:` and instead specify
:code:`profile: $PROVIDER_NAME` in the clouds.yml file.
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-1
:end-before: step-2
Flavors and images
~~~~~~~~~~~~~~~~~~
@ -321,6 +345,38 @@ To list the images that are available in your cloud, run some API calls:
Image Id: 3e0e8270-0da4-4fec-bfc7-eeb763604cad - Image Name: cirros-0.3.4-x86_64-uec-ramdisk
Image Id: 0b151382-d2f1-44d7-835b-6408bd523917 - Image Name: cirros-0.3.4-x86_64-uec-kernel
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:language: python
:start-after: step-2
:end-before: step-3
This code returns output like this:
.. code-block:: none
checksum: 750a56555d4ec7303f5dc33b007ff632
container_format: bare
created_at: '2014-07-14T19:02:15Z'
direct_url:
rbd://7e14670e-a6f8-445b-b632-4b79bafc4781/masseffect-images/b4efbc2a-6130-4f2e-b436-55a618c4de20/snap
disk_format: raw
file: /v2/images/b4efbc2a-6130-4f2e-b436-55a618c4de20/file
id: b4efbc2a-6130-4f2e-b436-55a618c4de20
min_disk: 10
min_ram: 1024
name: Debian-7.0-Wheezy
owner: 0bacd8121bb548698f340455b38bf561
protected: false
schema: /v2/schemas/image
size: 5242880000
status: active
tags: []
updated_at: '2014-10-15T22:42:52Z'
visibility: public
You can also get information about available flavors:
.. only:: fog
@ -388,13 +444,46 @@ You can also get information about available flavors:
Flavor Id: 5 - Flavor Name: m1.xlarge
Flavor Id: 84 - Flavor Name: m1.micro
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:language: python
:start-after: step-3
:end-before: step-4
This code returns output like this:
.. code-block:: none
HUMAN_ID: true
NAME_ATTR: name
OS-FLV-DISABLED:disabled: false
OS-FLV-EXT-DATA:ephemeral: 0
disk: 80
ephemeral: 0
human_id: supersonic
id: '200'
is_public: true
links:
- href:
https://compute.dream.io:8774/v2/5d013ac5962749a49af7ff18c2fb228c/flavors/200
rel: self
- href:
https://compute.dream.io:8774/5d013ac5962749a49af7ff18c2fb228c/flavors/200
rel: bookmark
name: supersonic
os-flavor-access:is_public: true
ram: 2048
swap: ''
vcpus: 1
Your images and flavors will be different, of course.
Choose an image and flavor for your instance. You need about 1GB RAM, 1 CPU,
and a 1GB disk. This example uses the Ubuntu image with the :code:`m1.small`
flavor, which are safe choices. In subsequent tutorial sections in this guide,
you must change the image and flavor IDs to correspond to the image and flavor
that you choose.
and a 1GB disk. This example uses the Ubuntu image with a small
flavor, which is a safe choice. In subsequent tutorial sections in
this guide, you must change the image and flavor IDs to correspond to
the image and flavor that you choose.
If the image that you want is not available in your cloud, you can usually
upload one depending on your cloud's policy settings. For information about
@ -455,6 +544,37 @@ image that you picked in the previous section:
Image Id: 97f55846-6ea5-4e9d-b437-bda97586bd0c - Image Name: cirros-0.3.4-x86_64-uec
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-4
:end-before: step-5
This code returns output like this:
.. code-block:: none
checksum: da578dd59289a35a0ac7744a0bd85cf5
container_format: bare
created_at: '2014-10-27T22:05:37Z'
direct_url:
rbd://7e14670e-a6f8-445b-b632-4b79bafc4781/masseffect-images/c55094e9-699c-4da9-95b4-2e2e75f4c66e/snap
disk_format: raw
file: /v2/images/c55094e9-699c-4da9-95b4-2e2e75f4c66e/file
id: c55094e9-699c-4da9-95b4-2e2e75f4c66e
min_disk: 0
min_ram: 0
name: Ubuntu-14.04-Trusty
owner: 0bacd8121bb548698f340455b38bf561
protected: false
schema: /v2/schemas/image
size: 10737418240
status: active
tags: []
updated_at: '2014-10-27T22:08:55Z'
visibility: public
Next, choose which flavor you want to use:
.. only:: fog
@ -506,6 +626,40 @@ Next, choose which flavor you want to use:
Flavor Id: 42 - Flavor Name: m1.nano
.. only:: shade
Since shade can either use the ID or the name in most API calls,
let's specify the name for the flavor.
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-5
:end-before: step-6
This code returns output like this:
.. code-block:: none
HUMAN_ID: true
NAME_ATTR: name
OS-FLV-DISABLED:disabled: false
OS-FLV-EXT-DATA:ephemeral: 0
disk: 80
ephemeral: 0
human_id: subsonic
id: '100'
is_public: true
links:
- href:
https://compute.dream.io:8774/v2/5d013ac5962749a49af7ff18c2fb228c/flavors/100
rel: self
- href:
https://compute.dream.io:8774/5d013ac5962749a49af7ff18c2fb228c/flavors/100
rel: bookmark
name: subsonic
os-flavor-access:is_public: true
ram: 1024
swap: ''
vcpus: 1
Now, you're ready to launch the instance.
@ -580,6 +734,12 @@ Create the instance.
Instance Id: 4e480ef1-68f0-491f-b237-d9b7f500ef24 at net.openstack.Core.Domain.Link[]
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-6
:end-before: step-7
If you list existing instances:
.. only:: fog
@ -608,6 +768,13 @@ If you list existing instances:
:start-after: step-7
:end-before: step-8
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-7
:end-before: step-8
The new instance appears.
.. only:: libcloud
@ -649,7 +816,72 @@ The new instance appears.
Instance Id: 4e480ef1-68f0-491f-b237-d9b7f500ef24 at net.openstack.Core.Domain.Link[]
Before you move on, you must do one more thing.
.. only:: shade
.. code-block:: none
HUMAN_ID: true
NAME_ATTR: name
OS-DCF:diskConfig: MANUAL
OS-EXT-AZ:availability_zone: iad-1
OS-EXT-STS:power_state: 1
OS-EXT-STS:task_state: null
OS-EXT-STS:vm_state: active
OS-SRV-USG:launched_at: '2015-07-20T20:31:10.000000'
OS-SRV-USG:terminated_at: null
accessIPv4: ''
accessIPv6: ''
addresses:
private-network:
- OS-EXT-IPS-MAC:mac_addr: fa:16:3e:60:f5:cd
OS-EXT-IPS:type: fixed
addr: 2607:f298:6050:4e14:f816:3eff:fe60:f5cd
version: 6
- OS-EXT-IPS-MAC:mac_addr: fa:16:3e:60:f5:cd
OS-EXT-IPS:type: fixed
addr: 10.10.10.14
version: 4
config_drive: ''
created: '2015-07-20T20:30:23Z'
flavor:
id: '100'
links:
- href:
https://compute.dream.io:8774/5d013ac5962749a49af7ff18c2fb228c/flavors/100
rel: bookmark
hostId: f71865b497e6fa71063e292b11846eb64b5a41cd5c00fbb7465b6a48
human_id: testing
id: 67ecebdc-daff-4d84-bd04-bc76c67b48ec
image:
id: c55094e9-699c-4da9-95b4-2e2e75f4c66e
links:
- href:
https://compute.dream.io:8774/5d013ac5962749a49af7ff18c2fb228c/images/c55094e9-699c-4da9-95b4-2e2e75f4c66e
rel: bookmark
key_name: null
links:
- href:
https://compute.dream.io:8774/v2/5d013ac5962749a49af7ff18c2fb228c/servers/67ecebdc-daff-4d84-bd04-bc76c67b48ec
rel: self
- href:
https://compute.dream.io:8774/5d013ac5962749a49af7ff18c2fb228c/servers/67ecebdc-daff-4d84-bd04-bc76c67b48ec
rel: bookmark
metadata: {}
name: testing
networks:
private-network:
- 2607:f298:6050:4e14:f816:3eff:fe60:f5cd
- 10.10.10.14
os-extended-volumes:volumes_attached: []
progress: 0
security_groups:
- name: default
status: ACTIVE
tenant_id: 5d013ac5962749a49af7ff18c2fb228c
updated: '2015-07-20T20:31:10Z'
user_id: bfd3dbf1c8a242cd90884408de547bb9
Before you continue, you must do one more thing.
Destroy an instance
~~~~~~~~~~~~~~~~~~~
@ -683,6 +915,12 @@ money. Destroy cloud resources to avoid unexpected expenses.
:start-after: step-8
:end-before: step-9
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-8
:end-before: step-9
If you list the instances again, the instance disappears.
Leave your shell open to use it for another instance deployment in this
@ -738,6 +976,16 @@ instance:
:start-after: step-9
:end-before: step-10
.. only:: shade
In the following example, :code:`pub_key_file` should be set to
the location of your public SSH key file.
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-9
:end-before: step-10
* Network access. By default, OpenStack filters all traffic. You must create
a security group and apply it to your instance. The security group allows HTTP
and SSH access. We'll go into more detail in :doc:`/introduction`.
@ -760,9 +1008,15 @@ instance:
:start-after: step-10
:end-before: step-11
* Userdata. During instance creation, you can provide userdata to OpenStack to
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-10
:end-before: step-11
* User data. During instance creation, you can provide user data to OpenStack to
configure instances after they boot. The cloud-init service applies the
userdata to an instance. You must pre-install the cloud-init service on your
user data to an instance. You must pre-install the cloud-init service on your
chosen image. We'll go into more detail in :doc:`/introduction`.
.. only:: fog
@ -781,6 +1035,12 @@ instance:
:start-after: step-11
:end-before: step-12
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-11
:end-before: step-12
Now, you can boot and configure the instance.
Boot and configure an instance
@ -805,6 +1065,13 @@ request the instance, wait for it to build.
:start-after: step-12
:end-before: step-13
.. only:: shade
The shade framework can select and assign a free floating IP quickly
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-12
:end-before: step-13
When the instance boots, the `ex_userdata` variable value instructs the
instance to deploy the Fractals application.
@ -871,6 +1138,12 @@ address to your instance.
:start-after: step-14
:end-before: step-15
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-13
:end-before: step-14
Run the script to start the deployment.
@ -880,7 +1153,7 @@ Access the application
Deploying application data and configuration to the instance can take some
time. Consider enjoying a cup of coffee while you wait. After the application
deploys, you can visit the awesome graphic interface at the following link
using your preferred browser.
by using your preferred browser.
.. only:: libcloud
@ -892,6 +1165,11 @@ using your preferred browser.
.. literalinclude:: ../samples/pkgcloud/getting_started.js
:start-after: step-15
.. only:: shade
.. literalinclude:: ../samples/shade/getting_started.py
:start-after: step-15
.. note:: If you do not use floating IPs, substitute another IP address as appropriate
.. figure:: images/screenshot_webinterface.png
@ -942,3 +1220,8 @@ information, the flavor ID, and image ID.
.. literalinclude:: ../samples/dotnet/getting_started.cs
:language: c#
.. only:: shade
.. literalinclude:: ../samples/libcloud/getting_started.py
:language: python

View File

@ -9,7 +9,7 @@ for tag in libcloud; do
done
# Draft documents
for tag in dotnet fog pkgcloud; do
for tag in dotnet fog pkgcloud shade; do
tools/build-rst.sh firstapp \
--tag ${tag} --target "draft/firstapp-${tag}"
done

View File

@ -109,6 +109,9 @@ commands = sphinx-build -E -W -t openstacksdk firstapp/source firstapp/build-ope
[testenv:firstapp-todos]
commands = sphinx-build -E -W -t libcloud firstapp/source firstapp/build/html
[testenv:firstapp-shade]
commands = sphinx-build -E -W -t shade firstapp/source firstapp/build-shade/html
[doc8]
# Settings for doc8:
# Ignore target directories