A better create server example

It's much more straight-forward for users to read a create server
example that does everything necessary to create the server
within the body of a single method. In this better example the user
doesn't have to refer to other examples to learn how to create a
server.

Change-Id: Iad7eef7946e93deb735fddcfbe39bbc8b56f507b
This commit is contained in:
Everett Toews 2015-10-30 15:57:38 -05:00
parent 7b0ba7bfbb
commit 6b2cec41d1
10 changed files with 127 additions and 43 deletions

View File

@ -6,13 +6,10 @@ clouds:
username: demo username: demo
password: secrete password: secrete
project_name: demo project_name: demo
hp: example:
cloud: hp image_name: fedora-20.x86_64
auth: flavor_name: m1.small
username: joe network_name: private
password: joes-password
project_name: joe-tenant1
region_name: region-b.geo-1
rackspace: rackspace:
cloud: rackspace cloud: rackspace
auth: auth:

View File

@ -56,8 +56,12 @@ Create Server
------------- -------------
At minimum, a server requires a name, an image, a flavor, and a network on At minimum, a server requires a name, an image, a flavor, and a network on
creation. Once you've discovered these attributes by listing them as above, creation. You can discover the names and IDs of these attributes by listing
you can create a server. them as above and then using the find methods to get the appropriate
resources.
Ideally you'll also create a server using a public/private keypair so you can
login to that server with the private key.
Servers take time to boot so we call ``wait_for_server`` to wait Servers take time to boot so we call ``wait_for_server`` to wait
for it to become active. for it to become active.

View File

@ -18,8 +18,7 @@ To create a connection you need a :class:`~openstack.profile.Profile` and a
:class:`~openstack.connection.Connection`. :class:`~openstack.connection.Connection`.
.. literalinclude:: ../examples/connect.py .. literalinclude:: ../examples/connect.py
:language: python :pyobject: create_connection
:lines: 32-44
The :class:`~openstack.profile.Profile` sets your preferences for each The :class:`~openstack.profile.Profile` sets your preferences for each
service. You will pass it the region of the OpenStack cloud that this service. You will pass it the region of the OpenStack cloud that this
@ -27,9 +26,9 @@ connection will use.
The :class:`~openstack.connection.Connection` is a context for a connection The :class:`~openstack.connection.Connection` is a context for a connection
to an OpenStack cloud. You will primarily use it to set the to an OpenStack cloud. You will primarily use it to set the
:class:`~openstack.profile.Profile` and authentication information with the :class:`~openstack.profile.Profile` and authentication information. You can
``auth_args`` parameter. You can also set the ``user_agent`` to something that also set the ``user_agent`` to something that describes your application
describes your application (e.g. ``my-web-app/1.3.4``). (e.g. ``my-web-app/1.3.4``).
Full example at `connect.py <http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/connect.py>`_ Full example at `connect.py <http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/connect.py>`_

View File

@ -19,13 +19,12 @@ Default Location
**************** ****************
To create a connection from a file you need a YAML file to contain the To create a connection from a file you need a YAML file to contain the
configuration and the :py:func:`~openstack.connection.from_config` configuration.
function.
.. literalinclude:: ../../contributors/clouds.yaml .. literalinclude:: ../../contributors/clouds.yaml
:language: yaml :language: yaml
To look for a configuration file called ``clouds.yaml`` in the default To use a configuration file called ``clouds.yaml`` in one of the default
locations: locations:
* Current Directory * Current Directory
@ -36,15 +35,17 @@ call :py:func:`~openstack.connection.from_config` with an object that has
the name of the cloud configuration to use. the name of the cloud configuration to use.
.. literalinclude:: ../examples/connect.py .. literalinclude:: ../examples/connect.py
:language: python :pyobject: Opts
:lines: 23-30
.. literalinclude:: ../examples/connect.py
:pyobject: create_connection_from_config
.. note:: To enable logging, set ``debug=True`` in the ``Opts`` object. .. note:: To enable logging, set ``debug=True`` in the ``Opts`` object.
User Defined Location User Defined Location
********************* *********************
To look for a configuration file in a user defined location set the To use a configuration file in a user defined location set the
environment variable ``OS_CLIENT_CONFIG_FILE`` to the environment variable ``OS_CLIENT_CONFIG_FILE`` to the
absolute path of a file.:: absolute path of a file.::
@ -54,8 +55,10 @@ and call :py:func:`~openstack.connection.from_config` with an object that has
the name of the cloud configuration to use. the name of the cloud configuration to use.
.. literalinclude:: ../examples/connect.py .. literalinclude:: ../examples/connect.py
:language: python :pyobject: Opts
:lines: 23-30
.. literalinclude:: ../examples/connect.py
:pyobject: create_connection_from_config
.. note:: To enable logging, set ``debug=True`` in the ``Opts`` object. .. note:: To enable logging, set ``debug=True`` in the ``Opts`` object.

View File

@ -10,6 +10,14 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import os
from examples.connect import FLAVOR_NAME
from examples.connect import IMAGE_NAME
from examples.connect import KEYPAIR_NAME
from examples.connect import NETWORK_NAME
from examples.connect import PRIVATE_KEYPAIR_FILE
""" """
Create resources with the Compute service. Create resources with the Compute service.
@ -17,12 +25,27 @@ For a full guide see TODO(etoews):link to docs on developer.openstack.org
""" """
def create_server(conn, name, image, flavor, network): def create_server(conn):
print("Create Server:") print("Create Server:")
server = conn.compute.create_server(name=name, image=image, image = conn.compute.find_image(IMAGE_NAME)
flavor=flavor, flavor = conn.compute.find_flavor(FLAVOR_NAME)
networks=[{"uuid": network.id}]) network = conn.network.find_network(NETWORK_NAME)
conn.compute.wait_for_server(server)
print(server) if not conn.compute.find_keypair(KEYPAIR_NAME):
keypair = conn.compute.create_keypair(name=KEYPAIR_NAME)
with open(PRIVATE_KEYPAIR_FILE, 'w') as f:
f.write("%s" % keypair.private_key)
os.chmod(PRIVATE_KEYPAIR_FILE, 0o400)
server = conn.compute.create_server(
name='openstacksdk-example', image=image, flavor=flavor,
networks=[{"uuid": network.id}], key_name=KEYPAIR_NAME)
server = conn.compute.wait_for_server(server)
print("ssh -i {key} root@{ip}".format(
key=PRIVATE_KEYPAIR_FILE,
ip=server.access_ipv4))

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import examples.connect
""" """
Find a resource from the Compute service. Find a resource from the Compute service.
@ -20,7 +22,7 @@ For a full guide see TODO(etoews):link to docs on developer.openstack.org
def find_image(conn): def find_image(conn):
print("Find Image:") print("Find Image:")
image = conn.compute.find_image("fedora-20.x86_64") image = conn.compute.find_image(examples.connect.IMAGE_NAME)
print(image) print(image)
@ -30,8 +32,18 @@ def find_image(conn):
def find_flavor(conn): def find_flavor(conn):
print("Find Flavor:") print("Find Flavor:")
flavor = conn.compute.find_flavor("m1.small") flavor = conn.compute.find_flavor(examples.connect.FLAVOR_NAME)
print(flavor) print(flavor)
return flavor return flavor
def find_keypair(conn):
print("Find Keypair:")
keypair = conn.compute.find_keypair(examples.connect.KEYPAIR_NAME)
print(keypair)
return keypair

View File

@ -36,3 +36,10 @@ def list_flavors(conn):
for flavor in conn.compute.flavors(): for flavor in conn.compute.flavors():
print(flavor) print(flavor)
def list_keypairs(conn):
print("List Keypairs:")
for keypair in conn.compute.keypairs():
print(keypair)

View File

@ -16,18 +16,53 @@ Connect to an OpenStack cloud.
For a full guide see TODO(etoews):link to docs on developer.openstack.org For a full guide see TODO(etoews):link to docs on developer.openstack.org
""" """
import os
import os_client_config
from openstack import connection from openstack import connection
from openstack import profile from openstack import profile
from openstack import utils
import sys
utils.enable_logging(True, stream=sys.stdout)
#: Defines the OpenStack Client Config (OCC) cloud key in your OCC config
#: file, typically in $HOME/.config/openstack/clouds.yaml. That configuration
#: will determine where the examples will be run and what resource defaults
#: will be used to run the examples.
TEST_CLOUD = os.getenv('OS_TEST_CLOUD', 'test_cloud')
class Opts(object): class Opts(object):
def __init__(self, cloud='hp', debug=False): def __init__(self, test_cloud='test_cloud', debug=False):
self.cloud = cloud self.cloud = test_cloud
self.debug = debug self.debug = debug
def _get_resource_value(resource_key, default):
try:
return cloud.config['example'][resource_key]
except KeyError:
return default
opts = Opts(test_cloud=TEST_CLOUD)
occ = os_client_config.OpenStackConfig()
cloud = occ.get_one_cloud(opts.cloud, argparse=opts)
IMAGE_NAME = _get_resource_value('image_name', 'fedora-20.x86_64')
FLAVOR_NAME = _get_resource_value('flavor_name', 'm1.small')
NETWORK_NAME = _get_resource_value('network_name', 'private')
KEYPAIR_NAME = _get_resource_value('keypair_name', 'openstacksdk-example')
PRIVATE_KEYPAIR_FILE = _get_resource_value('private_keypair_file',
"{home}/{ssh}/id_rsa.{key}".format(
home=os.getenv("HOME"),
ssh='.ssh',
key=KEYPAIR_NAME))
def create_connection_from_config(): def create_connection_from_config():
return connection.from_config(Opts(cloud='test_cloud')) return connection.from_config(opts)
def create_connection(auth_url, region, project_name, username, password): def create_connection(auth_url, region, project_name, username, password):

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import examples.connect
""" """
Find a resource from the Network service. Find a resource from the Network service.
@ -20,7 +22,7 @@ For a full guide see TODO(etoews):link to docs on developer.openstack.org
def find_network(conn): def find_network(conn):
print("Find Network:") print("Find Network:")
network = conn.network.find_network("public") network = conn.network.find_network(examples.connect.NETWORK_NAME)
print(network) print(network)

View File

@ -13,8 +13,8 @@
import unittest import unittest
from examples.compute import create from examples.compute import create
from examples.compute import find from examples.compute import find as compute_find
from examples.compute import list from examples.compute import list as compute_list
from examples import connect from examples import connect
from examples.network import find as network_find from examples.network import find as network_find
from examples.network import list as network_list from examples.network import list as network_list
@ -32,13 +32,15 @@ class TestCompute(unittest.TestCase):
cls.conn = connect.create_connection_from_config() cls.conn = connect.create_connection_from_config()
def test_compute(self): def test_compute(self):
list.list_servers(self.conn) compute_list.list_servers(self.conn)
list.list_images(self.conn) compute_list.list_images(self.conn)
list.list_flavors(self.conn) compute_list.list_flavors(self.conn)
compute_list.list_keypairs(self.conn)
network_list.list_networks(self.conn) network_list.list_networks(self.conn)
image = find.find_image(self.conn) compute_find.find_image(self.conn)
flavor = find.find_flavor(self.conn) compute_find.find_flavor(self.conn)
network = network_find.find_network(self.conn) compute_find.find_keypair(self.conn)
network_find.find_network(self.conn)
create.create_server(self.conn, 'example', image, flavor, network) create.create_server(self.conn)