From c1c6a0e9168762eed604c0ba7ec58b2c77247077 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Mon, 27 Mar 2023 11:28:00 +0100 Subject: [PATCH] docs: Replace/remove shade-specific docs Lots of minor tweaks, none of them worthy of their own change. Change-Id: Iba8649b8e12f367760849fd185cf76b94b703706 Signed-off-by: Stephen Finucane --- doc/source/contributor/coding.rst | 67 ++-- doc/source/contributor/history.rst | 61 +-- doc/source/contributor/index.rst | 1 - doc/source/contributor/layout.rst | 11 +- doc/source/contributor/setup.rst | 26 +- doc/source/index.rst | 1 - doc/source/install/index.rst | 1 - doc/source/releasenotes.rst | 1 - doc/source/user/index.rst | 1 - doc/source/user/microversions.rst | 1 - doc/source/user/model.rst | 560 ++------------------------- doc/source/user/multi-cloud-demo.rst | 216 ++++++----- doc/source/user/resource.rst | 4 - 13 files changed, 233 insertions(+), 718 deletions(-) diff --git a/doc/source/contributor/coding.rst b/doc/source/contributor/coding.rst index 9572d53d4..e1640e46d 100644 --- a/doc/source/contributor/coding.rst +++ b/doc/source/contributor/coding.rst @@ -1,24 +1,25 @@ -======================================== OpenStack SDK Developer Coding Standards ======================================== In the beginning, there were no guidelines. And it was good. But that didn't last long. As more and more people added more and more code, we realized that we needed a set of coding standards to make sure that -the openstacksdk API at least *attempted* to display some form of consistency. +the *openstacksdk* API at least *attempted* to display some form of +consistency. Thus, these coding standards/guidelines were developed. Note that not -all of openstacksdk adheres to these standards just yet. Some older code has +all of *openstacksdk* adheres to these standards just yet. Some older code has not been updated because we need to maintain backward compatibility. Some of it just hasn't been changed yet. But be clear, all new code *must* adhere to these guidelines. -Below are the patterns that we expect openstacksdk developers to follow. +Below are the patterns that we expect *openstacksdk* developers to follow. + Release Notes -============= +------------- -openstacksdk uses `reno `_ for +*openstacksdk* uses `reno `_ for managing its release notes. A new release note should be added to your contribution anytime you add new API calls, fix significant bugs, add new functionality or parameters to existing API calls, or make any @@ -29,56 +30,47 @@ It is *not* necessary to add release notes for minor fixes, such as correction of documentation typos, minor code cleanup or reorganization, or any other change that a user would not notice through normal usage. + Exceptions -========== +---------- Exceptions should NEVER be wrapped and re-raised inside of a new exception. This removes important debug information from the user. All of the exceptions should be raised correctly the first time. -openstack.cloud API Methods -=========================== -The `openstack.cloud` layer has some specific rules: +openstack.cloud API Methods +--------------------------- + +The ``openstack.cloud`` layer has some specific rules: - When an API call acts on a resource that has both a unique ID and a name, that API call should accept either identifier with a name_or_id parameter. - All resources should adhere to the get/list/search interface that - control retrieval of those resources. E.g., `get_image()`, `list_images()`, - `search_images()`. + control retrieval of those resources. E.g., ``get_image()``, + ``list_images()``, ``search_images()``. -- Resources should have `create_RESOURCE()`, `delete_RESOURCE()`, - `update_RESOURCE()` API methods (as it makes sense). +- Resources should have ``create_RESOURCE()``, ``delete_RESOURCE()``, + ``update_RESOURCE()`` API methods (as it makes sense). - For those methods that should behave differently for omitted or None-valued - parameters, use the `_utils.valid_kwargs` decorator. Notably: all Neutron - `update_*` functions. + parameters, use the ``_utils.valid_kwargs`` decorator. This includes all + Neutron ``update_*`` functions. - Deleting a resource should return True if the delete succeeded, or False if the resource was not found. Returned Resources ------------------- +~~~~~~~~~~~~~~~~~~ -Complex objects returned to the caller must be a `openstack.resource.Resource` -type. - -All objects should be normalized. It is openstacksdk's purpose in life to make -OpenStack consistent for end users, and this means not trusting the clouds -to return consistent objects. The `Resource` object should do this for us. - -Fields should not be in the normalization contract if we cannot commit to -providing them to all users. - -Fields should be renamed in normalization to be consistent with -the rest of `openstack.cloud`. For instance, nothing in `openstack.cloud` -exposes the legacy OpenStack concept of "tenant" to a user, but instead uses -"project" even if the cloud in question uses tenant. +The ``openstack.cloud`` layer should rely on the proxy layer for the given +service. This will ensure complex objects returned to the caller are of +``openstack.resource.Resource`` type. Nova vs. Neutron ----------------- +~~~~~~~~~~~~~~~~ - Recognize that not all cloud providers support Neutron, so never assume it will be present. If a task can be handled by either @@ -86,16 +78,17 @@ Nova vs. Neutron - For methods that accept either a Nova pool or Neutron network, the parameter should just refer to the network, but documentation of it - should explain about the pool. See: `create_floating_ip()` and - `available_floating_ip()` methods. + should explain about the pool. See: ``create_floating_ip()`` and + ``available_floating_ip()`` methods. + Tests -===== +----- - New API methods *must* have unit tests! -- New unit tests should only mock at the REST layer using `requests_mock`. - Any mocking of openstacksdk itself should be considered legacy and to be +- New unit tests should only mock at the REST layer using ``requests_mock``. + Any mocking of *openstacksdk* itself should be considered legacy and to be avoided. Exceptions to this rule can be made when attempting to test the internals of a logical shim where the inputs and output of the method aren't actually impacted by remote content. diff --git a/doc/source/contributor/history.rst b/doc/source/contributor/history.rst index 02a43f754..b2901ff3f 100644 --- a/doc/source/contributor/history.rst +++ b/doc/source/contributor/history.rst @@ -1,45 +1,46 @@ A Brief History =============== -openstacksdk started its life as three different libraries: shade, -os-client-config and python-openstacksdk. +*openstacksdk* started its life as three different libraries: *shade*, +*os-client-config* and *python-openstacksdk*. -``shade`` started its life as some code inside of OpenStack Infra's `nodepool`_ -project, and as some code inside of the `Ansible OpenStack Modules`_. -Ansible had a bunch of different OpenStack related modules, and there was a -ton of duplicated code. Eventually, between refactoring that duplication into -an internal library, and adding the logic and features that the OpenStack Infra -team had developed to run client applications at scale, it turned out that we'd -written nine-tenths of what we'd need to have a standalone library. +*shade* + *shade* started its life as some code inside of OpenStack Infra's `nodepool`_ + project, and as some code inside of the `Ansible OpenStack Modules`_. + Ansible had a bunch of different OpenStack related modules, and there was a + ton of duplicated code. Eventually, between refactoring that duplication into + an internal library, and adding the logic and features that the OpenStack + Infra team had developed to run client applications at scale, it turned out + that we'd written nine-tenths of what we'd need to have a standalone library. -Because of its background from nodepool, shade contained abstractions to -work around deployment differences and is resource oriented rather than service -oriented. This allows a user to think about Security Groups without having to -know whether Security Groups are provided by Nova or Neutron on a given cloud. -On the other hand, as an interface that provides an abstraction, it deviates -from the published OpenStack REST API and adds its own opinions, which may not -get in the way of more advanced users with specific needs. + Because of its background from nodepool, *shade* contained abstractions to + work around deployment differences and is resource oriented rather than + service oriented. This allows a user to think about Security Groups without + having to know whether Security Groups are provided by Nova or Neutron on a + given cloud. On the other hand, as an interface that provides an abstraction, + it deviates from the published OpenStack REST API and adds its own opinions, + which may not get in the way of more advanced users with specific needs. -``os-client-config`` was a library for collecting client configuration for -using an OpenStack cloud in a consistent and comprehensive manner, which -introduced the ``clouds.yaml`` file for expressing named cloud configurations. +*os-client-config* + *os-client-config* was a library for collecting client configuration for + using an OpenStack cloud in a consistent and comprehensive manner, which + introduced the ``clouds.yaml`` file for expressing named cloud + configurations. -``python-openstacksdk`` was a library that exposed the OpenStack APIs to -developers in a consistent and predictable manner. +*python-openstacksdk* + *python-openstacksdk* was a library that exposed the OpenStack APIs to + developers in a consistent and predictable manner. After a while it became clear that there was value in both the high-level layer that contains additional business logic and the lower-level SDK that exposes services and their resources faithfully and consistently as Python -objects. +objects. Even with both of those layers, it is still beneficial at times to be +able to make direct REST calls and to do so with the same properly configured +`Session`_ from `python-requests`_. This led to the merge of the three +projects. -Even with both of those layers, it is still beneficial at times to be able to -make direct REST calls and to do so with the same properly configured -`Session`_ from `python-requests`_. - -This led to the merge of the three projects. - -The original contents of the shade library have been moved into -``openstack.cloud`` and os-client-config has been moved in to +The original contents of the *shade* library have been moved into +``openstack.cloud`` and *os-client-config* has been moved in to ``openstack.config``. .. _nodepool: https://docs.openstack.org/infra/nodepool/ diff --git a/doc/source/contributor/index.rst b/doc/source/contributor/index.rst index 7d9be8eed..c651c76ec 100644 --- a/doc/source/contributor/index.rst +++ b/doc/source/contributor/index.rst @@ -1,4 +1,3 @@ -================================= Contributing to the OpenStack SDK ================================= diff --git a/doc/source/contributor/layout.rst b/doc/source/contributor/layout.rst index f96bb5632..b91d35985 100644 --- a/doc/source/contributor/layout.rst +++ b/doc/source/contributor/layout.rst @@ -80,9 +80,12 @@ method. For the time being, it simply passes on the ``Adapter`` maintained by the ``Proxy``, and returns what the underlying ``Resource.list`` method does. -The implementations and method signatures of ``Proxy`` methods are currently -under construction, as we figure out the best way to implement them in a -way which will apply nicely across all of the services. +Cloud +----- + +.. todo + +TODO. Connection ---------- @@ -93,7 +96,7 @@ higher level interface constructed of ``Proxy`` objects from each of the services. The ``Connection`` class' primary purpose is to act as a high-level interface -to this SDK, managing the lower level connecton bits and exposing the +to this SDK, managing the lower level connection bits and exposing the ``Resource`` objects through their corresponding `Proxy`_ object. If you've built proper ``Resource`` objects and implemented methods on the diff --git a/doc/source/contributor/setup.rst b/doc/source/contributor/setup.rst index 66109ac4b..36c5aa13b 100644 --- a/doc/source/contributor/setup.rst +++ b/doc/source/contributor/setup.rst @@ -5,20 +5,18 @@ Required Tools -------------- Python -****** +~~~~~~ As the OpenStack SDK is developed in Python, you will need at least one -version of Python installed. It is strongly preferred that you have at least -one of version 2 and one of version 3 so that your tests are run against both. -Our continuous integration system runs against several versions, so ultimately -we will have the proper test coverage, but having multiple versions locally -results in less time spent in code review when changes unexpectedly break -other versions. +version of Python installed. Our continuous integration system runs against +several versions, so ultimately we will have the proper test coverage, but +having multiple versions locally results in less time spent in code review when +changes unexpectedly break other versions. Python can be downloaded from https://www.python.org/downloads. virtualenv -********** +~~~~~~~~~~ In order to isolate our development environment from the system-based Python installation, we use `virtualenv `_. @@ -28,9 +26,9 @@ Virtualenv must be installed on your system in order to use it, and it can be had from PyPI, via pip, as follows. Note that you may need to run this as an administrator in some situations.:: - $ apt-get install python-virtualenv # Debian based platforms - $ yum install python-virtualenv # Red Hat based platforms - $ pip install virtualenv # Mac OS X and other platforms + $ apt-get install python3-virtualenv # Debian based platforms + $ dnf install python3-virtualenv # Red Hat based platforms + $ pip install virtualenv # Mac OS X and other platforms You can create a virtualenv in any location. A common usage is to store all of your virtualenvs in the same place, such as under your home directory. @@ -40,7 +38,7 @@ To create a virtualenv for the default Python, run the following:: To create an environment for a different version, run the following:: - $ virtualenv -p python3.8 $HOME/envs/sdk3 + $ virtualenv -p python3 $HOME/envs/sdk3 When you want to enable your environment so that you can develop inside of it, you *activate* it. To activate an environment, run the /bin/activate @@ -54,7 +52,7 @@ command prompt. In order to exit that environment, run the ``deactivate`` command. tox -*** +~~~ We use `tox `_ as our test runner, which allows us to run the same test commands against multiple versions @@ -64,7 +62,7 @@ run the following to install ``tox`` into it.:: (sdk3)$ pip install tox Git -*** +~~~ The source of the OpenStack SDK is stored in Git. In order to work with our source repository, you must have Git installed on your system. If your diff --git a/doc/source/index.rst b/doc/source/index.rst index c5a8c5d3a..d935708cd 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,4 +1,3 @@ -============ openstacksdk ============ diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst index 49cf87d5d..33255ae9a 100644 --- a/doc/source/install/index.rst +++ b/doc/source/install/index.rst @@ -1,4 +1,3 @@ -================== Installation guide ================== diff --git a/doc/source/releasenotes.rst b/doc/source/releasenotes.rst index 17b9814e2..b4eb5e488 100644 --- a/doc/source/releasenotes.rst +++ b/doc/source/releasenotes.rst @@ -1,4 +1,3 @@ -============= Release Notes ============= diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst index a78322772..0066080d0 100644 --- a/doc/source/user/index.rst +++ b/doc/source/user/index.rst @@ -1,4 +1,3 @@ -======================= Using the OpenStack SDK ======================= diff --git a/doc/source/user/microversions.rst b/doc/source/user/microversions.rst index a4960876e..fcef09656 100644 --- a/doc/source/user/microversions.rst +++ b/doc/source/user/microversions.rst @@ -1,4 +1,3 @@ -============= Microversions ============= diff --git a/doc/source/user/model.rst b/doc/source/user/model.rst index f6e7b4fbb..1c270e364 100644 --- a/doc/source/user/model.rst +++ b/doc/source/user/model.rst @@ -1,46 +1,47 @@ -========== Data Model ========== -shade has a very strict policy on not breaking backwards compatability ever. -However, with the data structures returned from OpenStack, there are places -where the resource structures from OpenStack are returned to the user somewhat -directly, leaving a shade user open to changes/differences in result content. +*openstacksdk* has a very strict policy on not breaking backwards compatibility +ever. However, with the data structures returned from OpenStack, there are +places where the resource structures from OpenStack are returned to the user +somewhat directly, leaving an openstacksdk user open to changes/differences in +result content. -To combat that, shade 'normalizes' the return structure from OpenStack in many -places, and the results of that normalization are listed below. Where shade -performs normalization, a user can count on any fields declared in the docs -as being completely safe to use - they are as much a part of shade's API -contract as any other Python method. +To combat that, openstacksdk 'normalizes' the return structure from OpenStack +in many places, and the results of that normalization are listed below. Where +openstacksdk performs normalization, a user can count on any fields declared in +the docs as being completely safe to use - they are as much a part of +openstacksdk's API contract as any other Python method. -Some OpenStack objects allow for arbitrary attributes at -the root of the object. shade will pass those through so as not to break anyone -who may be counting on them, but as they are arbitrary shade can make no -guarantees as to their existence. As part of normalization, shade will put any -attribute from an OpenStack resource that is not in its data model contract -into an attribute called 'properties'. The contents of properties are -defined to be an arbitrary collection of key value pairs with no promises as -to any particular key ever existing. +Some OpenStack objects allow for arbitrary attributes at the root of the +object. openstacksdk will pass those through so as not to break anyone who may +be counting on them, but as they are arbitrary openstacksdk can make no +guarantees as to their existence. As part of normalization, openstacksdk will +put any attribute from an OpenStack resource that is not in its data model +contract into an attribute called 'properties'. The contents of properties are +defined to be an arbitrary collection of key value pairs with no promises as to +any particular key ever existing. -If a user passes `strict=True` to the shade constructor, shade will not pass -through arbitrary objects to the root of the resource, and will instead only -put them in the properties dict. If a user is worried about accidentally -writing code that depends on an attribute that is not part of the API contract, -this can be a useful tool. Keep in mind all data can still be accessed via -the properties dict, but any code touching anything in the properties dict -should be aware that the keys found there are highly user/cloud specific. -Any key that is transformed as part of the shade data model contract will -not wind up with an entry in properties - only keys that are unknown. +If a user passes ``strict=True`` to the openstacksdk constructor, openstacksdk +will not pass through arbitrary objects to the root of the resource, and will +instead only put them in the properties dict. If a user is worried about +accidentally writing code that depends on an attribute that is not part of the +API contract, this can be a useful tool. Keep in mind all data can still be +accessed via the properties dict, but any code touching anything in the +properties dict should be aware that the keys found there are highly user/cloud +specific. Any key that is transformed as part of the openstacksdk data model +contract will not wind up with an entry in properties - only keys that are +unknown. -Location --------- +The ``location`` field +---------------------- A Location defines where a resource lives. It includes a cloud name and a region name, an availability zone as well as information about the project that owns the resource. -The project information may contain a project id, or a combination of one or -more of a project name with a domain name or id. If a project id is present, +The project information may contain a project ID, or a combination of one or +more of a project name with a domain name or ID. If a project ID is present, it should be considered correct. Some resources do not carry ownership information with them. For those, the @@ -50,491 +51,16 @@ has a token for. Some resources do not have information about availability zones, or may exist region wide. Those resources will have None as their availability zone. -If all of the project information is None, then - .. code-block:: python - Location = dict( - cloud=str(), - region_name=str(), - zone=str() or None, - project=dict( - id=str() or None, - name=str() or None, - domain_id=str() or None, - domain_name=str() or None)) - - -Resources -========= - -Flavor ------- - -A flavor for a Nova Server. - -.. code-block:: python - - Flavor = dict( - location=Location(), - id=str(), - name=str(), - is_public=bool(), - is_disabled=bool(), - ram=int(), - vcpus=int(), - disk=int(), - ephemeral=int(), - swap=int(), - rxtx_factor=float(), - extra_specs=dict(), - properties=dict()) - - -Flavor Access -------------- - -An access entry for a Nova Flavor. - -.. code-block:: python - - FlavorAccess = dict( - flavor_id=str(), - project_id=str()) - - -Image ------ - -A Glance Image. - -.. code-block:: python - - Image = dict( - location=Location(), - id=str(), - name=str(), - min_ram=int(), - min_disk=int(), - size=int(), - virtual_size=int(), - container_format=str(), - disk_format=str(), - checksum=str(), - created_at=str(), - updated_at=str(), - owner=str(), - is_public=bool(), - is_protected=bool(), - visibility=str(), - status=str(), - locations=list(), - direct_url=str() or None, - tags=list(), - properties=dict()) - - -Keypair -------- - -A keypair for a Nova Server. - -.. code-block:: python - - Keypair = dict( - location=Location(), - name=str(), - id=str(), - public_key=str(), - fingerprint=str(), - type=str(), - user_id=str(), - private_key=str() or None - properties=dict()) - - -Security Group --------------- - -A Security Group from either Nova or Neutron - -.. code-block:: python - - SecurityGroup = dict( - location=Location(), - id=str(), - name=str(), - description=str(), - security_group_rules=list(), - properties=dict()) - -Security Group Rule -------------------- - -A Security Group Rule from either Nova or Neutron - -.. code-block:: python - - SecurityGroupRule = dict( - location=Location(), - id=str(), - direction=str(), # oneof('ingress', 'egress') - ethertype=str(), - port_range_min=int() or None, - port_range_max=int() or None, - protocol=str() or None, - remote_ip_prefix=str() or None, - security_group_id=str() or None, - remote_group_id=str() or None - properties=dict()) - -Server ------- - -A Server from Nova - -.. code-block:: python - - Server = dict( - location=Location(), - id=str(), - name=str(), - image=dict() or str(), - flavor=dict(), - volumes=list(), # Volume - interface_ip=str(), - has_config_drive=bool(), - accessIPv4=str(), - accessIPv6=str(), - addresses=dict(), # string, list(Address) - created=str(), - created_at=str(), - key_name=str(), - metadata=dict(), # string, string - private_v4=str(), - progress=int(), - public_v4=str(), - public_v6=str(), - security_groups=list(), # SecurityGroup - status=str(), - updated=str(), - user_id=str(), - host_id=str() or None, - power_state=str() or None, - task_state=str() or None, - vm_state=str() or None, - launched_at=str() or None, - terminated_at=str() or None, - task_state=str() or None, - block_device_mapping=dict() or None, - instance_name=str() or None, - hypervisor_name=str() or None, - tags=list(), - personality=str() or None, - scheduler_hints=str() or None, - user_data=str() or None, - properties=dict()) - -ComputeLimits -------------- - -Limits and current usage for a project in Nova - -.. code-block:: python - - ComputeLimits = dict( - location=Location(), - max_personality=int(), - max_personality_size=int(), - max_server_group_members=int(), - max_server_groups=int(), - max_server_meta=int(), - max_total_cores=int(), - max_total_instances=int(), - max_total_keypairs=int(), - max_total_ram_size=int(), - total_cores_used=int(), - total_instances_used=int(), - total_ram_used=int(), - total_server_groups_used=int(), - properties=dict()) - -ComputeUsage ------------- - -Current usage for a project in Nova - -.. code-block:: python - - ComputeUsage = dict( - location=Location(), - started_at=str(), - stopped_at=str(), - server_usages=list(), - max_personality=int(), - max_personality_size=int(), - max_server_group_members=int(), - max_server_groups=int(), - max_server_meta=int(), - max_total_cores=int(), - max_total_instances=int(), - max_total_keypairs=int(), - max_total_ram_size=int(), - total_cores_used=int(), - total_hours=int(), - total_instances_used=int(), - total_local_gb_usage=int(), - total_memory_mb_usage=int(), - total_ram_used=int(), - total_server_groups_used=int(), - total_vcpus_usage=int(), - properties=dict()) - -ServerUsage ------------ - -Current usage for a server in Nova - -.. code-block:: python - - ComputeUsage = dict( - started_at=str(), - ended_at=str(), - flavor=str(), - hours=int(), - instance_id=str(), - local_gb=int(), - memory_mb=int(), - name=str(), - state=str(), - uptime=int(), - vcpus=int(), - properties=dict()) - -Floating IP ------------ - -A Floating IP from Neutron or Nova - - -.. code-block:: python - - FloatingIP = dict( - location=Location(), - id=str(), - description=str(), - attached=bool(), - fixed_ip_address=str() or None, - floating_ip_address=str() or None, - network=str() or None, - port=str() or None, - router=str(), - status=str(), - created_at=str() or None, - updated_at=str() or None, - revision_number=int() or None, - properties=dict()) - -Volume ------- - -A volume from cinder. - -.. code-block:: python - - Volume = dict( - location=Location(), - id=str(), - name=str(), - description=str(), - size=int(), - attachments=list(), - status=str(), - migration_status=str() or None, - host=str() or None, - replication_driver=str() or None, - replication_status=str() or None, - replication_extended_status=str() or None, - snapshot_id=str() or None, - created_at=str(), - updated_at=str() or None, - source_volume_id=str() or None, - consistencygroup_id=str() or None, - volume_type=str() or None, - metadata=dict(), - is_bootable=bool(), - is_encrypted=bool(), - can_multiattach=bool(), - properties=dict()) - - -VolumeType ----------- - -A volume type from cinder. - -.. code-block:: python - - VolumeType = dict( - location=Location(), - id=str(), - name=str(), - description=str() or None, - is_public=bool(), - qos_specs_id=str() or None, - extra_specs=dict(), - properties=dict()) - - -VolumeTypeAccess ----------------- - -A volume type access from cinder. - -.. code-block:: python - - VolumeTypeAccess = dict( - location=Location(), - volume_type_id=str(), - project_id=str(), - properties=dict()) - - -ClusterTemplate ---------------- - -A Cluster Template from magnum. - -.. code-block:: python - - ClusterTemplate = dict( - location=Location(), - apiserver_port=int(), - cluster_distro=str(), - coe=str(), - created_at=str(), - dns_nameserver=str(), - docker_volume_size=int(), - external_network_id=str(), - fixed_network=str() or None, - flavor_id=str(), - http_proxy=str() or None, - https_proxy=str() or None, - id=str(), - image_id=str(), - insecure_registry=str(), - is_public=bool(), - is_registry_enabled=bool(), - is_tls_disabled=bool(), - keypair_id=str(), - labels=dict(), - master_flavor_id=str() or None, - name=str(), - network_driver=str(), - no_proxy=str() or None, - server_type=str(), - updated_at=str() or None, - volume_driver=str(), - properties=dict()) - -MagnumService -------------- - -A Magnum Service from magnum - -.. code-block:: python - - MagnumService = dict( - location=Location(), - binary=str(), - created_at=str(), - disabled_reason=str() or None, - host=str(), - id=str(), - report_count=int(), - state=str(), - properties=dict()) - -Stack ------ - -A Stack from Heat - -.. code-block:: python - - Stack = dict( - location=Location(), - id=str(), - name=str(), - created_at=str(), - deleted_at=str(), - updated_at=str(), - description=str(), - action=str(), - identifier=str(), - is_rollback_enabled=bool(), - notification_topics=list(), - outputs=list(), - owner=str(), - parameters=dict(), - parent=str(), - stack_user_project_id=str(), - status=str(), - status_reason=str(), - tags=dict(), - tempate_description=str(), - timeout_mins=int(), - properties=dict()) - -Identity Resources -================== - -Identity Resources are slightly different. - -They are global to a cloud, so location.availability_zone and -location.region_name and will always be None. If a deployer happens to deploy -OpenStack in such a way that users and projects are not shared amongst regions, -that necessitates treating each of those regions as separate clouds from -shade's POV. - -The Identity Resources that are not Project do not exist within a Project, -so all of the values in ``location.project`` will be None. - -Project -------- - -A Project from Keystone (or a tenant if Keystone v2) - -Location information for Project has some additional specific semantics. -If the project has a parent project, that will be in ``location.project.id``, -and if it doesn't that should be ``None``. - -If the Project is associated with a domain that will be in -``location.project.domain_id`` in addition to the normal ``domain_id`` -regardless of the current user's token scope. - -.. code-block:: python - - Project = dict( - location=Location(), - id=str(), - name=str(), - description=str(), - is_enabled=bool(), - is_domain=bool(), - domain_id=str(), - properties=dict()) - -Role ----- - -A Role from Keystone - -.. code-block:: python - - Project = dict( - location=Location(), - id=str(), - name=str(), - domain_id=str(), - properties=dict()) + Location = dict( + cloud=str(), + region_name=str(), + zone=str() or None, + project=dict( + id=str() or None, + name=str() or None, + domain_id=str() or None, + domain_name=str() or None, + ) + ) diff --git a/doc/source/user/multi-cloud-demo.rst b/doc/source/user/multi-cloud-demo.rst index 710055df4..7aace3f3c 100644 --- a/doc/source/user/multi-cloud-demo.rst +++ b/doc/source/user/multi-cloud-demo.rst @@ -1,4 +1,3 @@ -================ Multi-Cloud Demo ================ @@ -10,15 +9,12 @@ walk through it like a presentation, install `presentty` and run: presentty doc/source/user/multi-cloud-demo.rst The content is hopefully helpful even if it's not being narrated, so it's being -included in the `shade` docs. +included in the openstacksdk docs. .. _presentty: https://pypi.org/project/presentty -Using Multiple OpenStack Clouds Easily with Shade -================================================= - Who am I? -========= +--------- Monty Taylor @@ -27,7 +23,7 @@ Monty Taylor * twitter: @e_monty What are we going to talk about? -================================ +-------------------------------- `OpenStackSDK` @@ -43,22 +39,22 @@ What are we going to talk about? * Librified to re-use in Ansible OpenStackSDK is Free Software -============================= +----------------------------- * https://opendev.org/openstack/openstacksdk * openstack-discuss@lists.openstack.org * #openstack-sdks on oftc This talk is Free Software, too -=============================== +------------------------------- * Written for presentty (https://pypi.org/project/presentty) -* doc/source/multi-cloud-demo.rst -* examples in doc/source/examples -* Paths subject to change- this is the first presentation in tree! +* doc/source/user/multi-cloud-demo.rst +* examples in examples/cloud +* Paths subject to change - this is the first presentation in tree! Complete Example -================ +---------------- .. code:: python @@ -68,15 +64,19 @@ Complete Example openstack.enable_logging(debug=True) for cloud_name, region_name in [ - ('my-vexxhost', 'ca-ymq-1'), - ('my-citycloud', 'Buf1'), - ('my-internap', 'ams01')]: + ('my-vexxhost', 'ca-ymq-1'), + ('my-citycloud', 'Buf1'), + ('my-internap', 'ams01'), + ]: # Initialize cloud cloud = openstack.connect(cloud=cloud_name, region_name=region_name) # Upload an image to the cloud image = cloud.create_image( - 'devuan-jessie', filename='devuan-jessie.qcow2', wait=True) + 'devuan-jessie', + filename='devuan-jessie.qcow2', + wait=True, + ) # Find a flavor with at least 512M of RAM flavor = cloud.get_flavor_by_ram(512) @@ -84,19 +84,24 @@ Complete Example # Boot a server, wait for it to boot, and then do whatever is needed # to get a public ip for it. cloud.create_server( - 'my-server', image=image, flavor=flavor, wait=True, auto_ip=True) + 'my-server', + image=image, + flavor=flavor, + wait=True, + auto_ip=True, + ) Let's Take a Few Steps Back -=========================== +--------------------------- Multi-cloud is easy, but you need to know a few things. * Terminology * Config -* Shade API +* OpenStackSDK API Cloud Terminology -================= +----------------- Let's define a few terms, so that we can use them with ease: @@ -108,7 +113,7 @@ Let's define a few terms, so that we can use them with ease: * `domain` - collection of users and projects Cloud Terminology Relationships -=============================== +------------------------------- * A `cloud` has one or more `regions` * A `patron` has one or more `users` @@ -121,14 +126,14 @@ Cloud Terminology Relationships * A `user` has one or more `roles` on one or more `projects` HTTP Sessions -============= +------------- * HTTP interactions are authenticated via keystone * Authenticating returns a `token` * An authenticated HTTP Session is shared across a `region` Cloud Regions -============= +------------- A `cloud region` is the basic unit of REST interaction. @@ -138,7 +143,7 @@ A `cloud region` is the basic unit of REST interaction. * A `region` is completely autonomous Users, Projects and Domains -=========================== +--------------------------- In clouds with multiple domains, project and user names are only unique within a region. @@ -151,12 +156,12 @@ only unique within a region. * `user_id` does not Confused Yet? -============= +------------- Don't worry - you don't have to deal with most of that. Auth per cloud, select per region -================================= +--------------------------------- In general, the thing you need to know is: @@ -164,7 +169,7 @@ In general, the thing you need to know is: * Select config to use by `cloud` and `region` clouds.yaml -=========== +----------- Information about the clouds you want to connect to is stored in a file called `clouds.yaml`. @@ -178,7 +183,7 @@ Full docs on `clouds.yaml` are at https://docs.openstack.org/os-client-config/latest/ What about Mac and Windows? -=========================== +--------------------------- `USER_CONFIG_DIR` is different on Linux, OSX and Windows. @@ -193,7 +198,7 @@ What about Mac and Windows? * Windows: `C:\\ProgramData\\OpenStack\\openstack` Config Terminology -================== +------------------ For multi-cloud, think of two types: @@ -203,7 +208,7 @@ For multi-cloud, think of two types: Apologies for the use of `cloud` twice. Environment Variables and Simple Usage -====================================== +-------------------------------------- * Environment variables starting with `OS_` go into a cloud called `envvars` * If you only have one cloud, you don't have to specify it @@ -211,10 +216,10 @@ Environment Variables and Simple Usage `cloud` and `region_name` TOO MUCH TALKING - NOT ENOUGH CODE -================================== +---------------------------------- basic clouds.yaml for the example code -====================================== +-------------------------------------- Simple example of a clouds.yaml @@ -239,14 +244,14 @@ Simple example of a clouds.yaml Where's the password? secure.yaml -=========== +----------- * Optional additional file just like `clouds.yaml` * Values overlaid on `clouds.yaml` * Useful if you want to protect secrets more stringently Example secure.yaml -=================== +------------------- * No, my password isn't XXXXXXXX * `cloud` name should match `clouds.yaml` @@ -260,7 +265,7 @@ Example secure.yaml password: XXXXXXXX more clouds.yaml -================ +---------------- More information can be provided. @@ -281,7 +286,7 @@ More information can be provided. username: 0b8c435b-cc4d-4e05-8a47-a2ada0539af1 Much more complex clouds.yaml example -===================================== +------------------------------------- * Not using a profile - all settings included * In the `ams01` `region` there are two networks with undiscoverable qualities @@ -310,7 +315,7 @@ Much more complex clouds.yaml example routes_externally: false Complete Example Again -====================== +---------------------- .. code:: python @@ -339,17 +344,17 @@ Complete Example Again 'my-server', image=image, flavor=flavor, wait=True, auto_ip=True) Step By Step -============ +------------ Import the library -================== +------------------ .. code:: python from openstack import cloud as openstack Logging -======= +------- * `openstacksdk` uses standard python logging * ``openstack.enable_logging`` does easy defaults @@ -357,7 +362,7 @@ Logging * `debug` - * Logs shade loggers at debug level + * Logs openstacksdk loggers at debug level * `http_debug` Implies `debug`, turns on HTTP tracing @@ -367,23 +372,22 @@ Logging openstack.enable_logging(debug=True) Example with Debug Logging -========================== +-------------------------- -* doc/source/examples/debug-logging.py +* examples/cloud/debug-logging.py .. code:: python from openstack import cloud as openstack openstack.enable_logging(debug=True) - cloud = openstack.connect( - cloud='my-vexxhost', region_name='ca-ymq-1') + cloud = openstack.connect(cloud='my-vexxhost', region_name='ca-ymq-1') cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]') Example with HTTP Debug Logging -=============================== +------------------------------- -* doc/source/examples/http-debug-logging.py +* examples/cloud/http-debug-logging.py .. code:: python @@ -395,7 +399,7 @@ Example with HTTP Debug Logging cloud.get_image('Ubuntu 16.04.1 LTS [2017-03-03]') Cloud Regions -============= +------------- * `cloud` constructor needs `cloud` and `region_name` * `openstack.connect` is a helper factory function @@ -403,14 +407,15 @@ Cloud Regions .. code:: python for cloud_name, region_name in [ - ('my-vexxhost', 'ca-ymq-1'), - ('my-citycloud', 'Buf1'), - ('my-internap', 'ams01')]: + ('my-vexxhost', 'ca-ymq-1'), + ('my-citycloud', 'Buf1'), + ('my-internap', 'ams01') + ]: # Initialize cloud cloud = openstack.connect(cloud=cloud_name, region_name=region_name) Upload an Image -=============== +--------------- * Picks the correct upload mechanism * **SUGGESTION** Always upload your own base images @@ -419,10 +424,13 @@ Upload an Image # Upload an image to the cloud image = cloud.create_image( - 'devuan-jessie', filename='devuan-jessie.qcow2', wait=True) + 'devuan-jessie', + filename='devuan-jessie.qcow2', + wait=True, + ) Always Upload an Image -====================== +---------------------- Ok. You don't have to. But, for multi-cloud... @@ -432,7 +440,7 @@ Ok. You don't have to. But, for multi-cloud... * Download from OS vendor or build with `diskimage-builder` Find a flavor -============= +------------- * Flavors are all named differently on clouds * Flavors can be found via RAM @@ -444,7 +452,7 @@ Find a flavor flavor = cloud.get_flavor_by_ram(512) Create a server -=============== +--------------- * my-vexxhost @@ -472,15 +480,15 @@ Create a server 'my-server', image=image, flavor=flavor, wait=True, auto_ip=True) Wow. We didn't even deploy Wordpress! -===================================== +------------------------------------- Image and Flavor by Name or ID -============================== +------------------------------ * Pass string to image/flavor * Image/Flavor will be found by name or ID * Common pattern -* doc/source/examples/create-server-name-or-id.py +* examples/cloud/create-server-name-or-id.py .. code:: python @@ -509,11 +517,8 @@ Image and Flavor by Name or ID # Delete it - this is a demo cloud.delete_server(server, wait=True, delete_ips=True) -cloud.pprint method was just added this morning -=============================================== - Delete Servers -============== +-------------- * `delete_ips` Delete any `floating_ips` the server may have @@ -522,12 +527,12 @@ Delete Servers cloud.delete_server('my-server', wait=True, delete_ips=True) Image and Flavor by Dict -======================== +------------------------ * Pass dict to image/flavor * If you know if the value is Name or ID * Common pattern -* doc/source/examples/create-server-dict.py +* examples/cloud/create-server-dict.py .. code:: python @@ -555,10 +560,10 @@ Image and Flavor by Dict cloud.delete_server(server, wait=True, delete_ips=True) Munch Objects -============= +------------- * Behave like a dict and an object -* doc/source/examples/munch-dict-object.py +* examples/cloud/munch-dict-object.py .. code:: python @@ -571,7 +576,7 @@ Munch Objects print(image['name']) API Organized by Logical Resource -================================= +--------------------------------- * list_servers * search_servers @@ -587,10 +592,10 @@ For other things, it's still {verb}_{noun} * add_auto_ip Cleanup Script -============== +-------------- * Sometimes my examples had bugs -* doc/source/examples/cleanup-servers.py +* examples/cloud/cleanup-servers.py .. code:: python @@ -609,10 +614,9 @@ Cleanup Script cloud.delete_server(server, wait=True, delete_ips=True) Normalization -============= +------------- -* https://docs.openstack.org/shade/latest/user/model.html#image -* doc/source/examples/normalization.py +* examples/cloud/normalization.py .. code:: python @@ -625,10 +629,10 @@ Normalization cloud.pprint(image) Strict Normalized Results -========================= +------------------------- * Return only the declared model -* doc/source/examples/strict-mode.py +* examples/cloud/strict-mode.py .. code:: python @@ -642,10 +646,10 @@ Strict Normalized Results cloud.pprint(image) How Did I Find the Image Name for the Last Example? -=================================================== +--------------------------------------------------- * I often make stupid little utility scripts -* doc/source/examples/find-an-image.py +* examples/cloud/find-an-image.py .. code:: python @@ -658,7 +662,7 @@ How Did I Find the Image Name for the Last Example? if 'ubuntu' in image.name.lower()]) Added / Modified Information -============================ +---------------------------- * Servers need more extra help * Fetch addresses dict from neutron @@ -666,7 +670,7 @@ Added / Modified Information * `detailed` - defaults to True, add everything * `bare` - no extra calls - don't even fix broken things * `bare` is still normalized -* doc/source/examples/server-information.py +* examples/cloud/server-information.py .. code:: python @@ -694,9 +698,9 @@ Added / Modified Information cloud.delete_server(server, wait=True, delete_ips=True) Exceptions -========== +---------- -* All shade exceptions are subclasses of `OpenStackCloudException` +* All openstacksdk exceptions are subclasses of `OpenStackCloudException` * Direct REST calls throw `OpenStackCloudHTTPError` * `OpenStackCloudHTTPError` subclasses `OpenStackCloudException` and `requests.exceptions.HTTPError` @@ -704,11 +708,11 @@ Exceptions * `OpenStackCloudBadRequest` for 400 User Agent Info -=============== +--------------- * Set `app_name` and `app_version` for User Agents -* (sssh ... `region_name` is optional if the cloud has one region) -* doc/source/examples/user-agent.py +* (ssh ... `region_name` is optional if the cloud has one region) +* examples/cloud/user-agent.py .. code:: python @@ -716,17 +720,20 @@ User Agent Info openstack.enable_logging(http_debug=True) cloud = openstack.connect( - cloud='datacentred', app_name='AmazingApp', app_version='1.0') + cloud='datacentred', + app_name='AmazingApp', + app_version='1.0', + ) cloud.list_networks() Uploading Large Objects -======================= +----------------------- * swift has a maximum object size * Large Objects are uploaded specially -* shade figures this out and does it +* openstacksdk figures this out and does it * multi-threaded -* doc/source/examples/upload-object.py +* examples/cloud/upload-object.py .. code:: python @@ -735,19 +742,21 @@ Uploading Large Objects cloud = openstack.connect(cloud='ovh', region_name='SBG1') cloud.create_object( - container='my-container', name='my-object', - filename='/home/mordred/briarcliff.sh3d') + container='my-container', + name='my-object', + filename='/home/mordred/briarcliff.sh3d', + ) cloud.delete_object('my-container', 'my-object') cloud.delete_container('my-container') Uploading Large Objects -======================= +----------------------- * Default max_file_size is 5G * This is a conference demo * Let's force a segment_size * One MILLION bytes -* doc/source/examples/upload-object.py +* examples/cloud/upload-object.py .. code:: python @@ -756,14 +765,16 @@ Uploading Large Objects cloud = openstack.connect(cloud='ovh', region_name='SBG1') cloud.create_object( - container='my-container', name='my-object', + container='my-container', + name='my-object', filename='/home/mordred/briarcliff.sh3d', - segment_size=1000000) + segment_size=1000000, + ) cloud.delete_object('my-container', 'my-object') cloud.delete_container('my-container') Service Conditionals -==================== +-------------------- .. code:: python @@ -775,7 +786,7 @@ Service Conditionals print(cloud.has_service('container-orchestration')) Service Conditional Overrides -============================= +----------------------------- * Sometimes clouds are weird and figuring that out won't work @@ -798,12 +809,5 @@ Service Conditional Overrides # This is already in profile: rackspace has_network: false -Coming Soon -=========== - -* Completion of RESTification -* Full version discovery support -* Multi-cloud facade layer -* Microversion support (talk tomorrow) -* Completion of caching tier (talk tomorrow) -* All of you helping hacking on shade!!! (we're friendly) +FIN +--- diff --git a/doc/source/user/resource.rst b/doc/source/user/resource.rst index 8453265f5..c7b5ae2d9 100644 --- a/doc/source/user/resource.rst +++ b/doc/source/user/resource.rst @@ -1,7 +1,3 @@ -**Note: This class is in the process of being applied as the new base class -for resources around the OpenStack SDK. Once that has been completed, -this module will be drop the 2 suffix and be the only resource module.** - Resource ======== .. automodule:: openstack.resource